最近让AI帮忙做的一些事

67°C 29-06-2026 notbyai
最近更新于:2026-06-29 14:59:29

文章摘要moonshot-v1-8k

Standby API Responsing..

2026年,AI确实越来越聪明了。如果说早期的AI需要非常专业的prompt来辅助,现在已经发展到不太需要那么专业了,不论日常交流,学术研讨还是技术实现,从文字到音频,再从图片到视频,AI“猜”用户需求的能力毫无疑问已经越来越强了,AI能帮我们做的也越来越多。

最近做了两个事,一个是迁移valine评论,另一个是给wordpress的评论系统加了一些AI辅助。促使这次改版的是偶然看到了corrain 博文评论区中@AI自动回复,觉得和微信元宝很像,很方便,就想着改进一下wp评论。(其实凡哥那早就做了ai评论,当然,后续增强AI评论也是参考了该逻辑)

开发的时候我都没用最强coding claude,用的国产deepseek的专家模式,开启深度思考,现在实际体验真的很不错了。他的模型数据很大,我直接把问题抛给它,其中很多没提供的细节都是他自己拿到的。虽然不是什么一次成功,但效率提升不是一点半点。

@2BER AI

因为 Valine 即将关闭服务,故此项在 wordpress 基础上开发。

先说下这个 @2BER 评论增强AI,2BER被设计用来评论用户交流互动,支持文章摘要。一开始设计他的目的还是文章总结,不过后来发现当AI被设计到评论交互系统里后就变得特别灵活,可扩展性特别强。当你在文章下 @2BER (但不回复任何内容)时会自动返回当前文章摘要,在其他页面 @2BER 时,他会作为一名普通AI助手和你聊天。后面我发现这样功能还有点单一,就再增强了他的属性,设计了多楼层评论、解析其他用户评论、多轮对话等复杂结构。

这gpt生成的图片就是漂亮🤭

期间AI回复体验比之前好很多,很多你没考虑到的东西他会自己去设计并告知你具体用途,其实开启深度思考也有用,看看他的思路是什么,有时候他会抛弃掉部分实现思路,但是你能看见,就可以在他后续代码出错时尝试他之前的思路,有时候有奇效👍。

基础需求
// 需求:wordpress评论系统增加`@2BER`关键词触发AI自动回复用户评论内容,思路:通过`comment_post`钩子,截取检测评论内容若包含该关键词,则携带文章内容+用户需求发送到指定api请求给ai的api(如kimi),并等待api返回结果,将此结果(文本)作为该用户的子评论回复。
..
新增 REST API
// 对了,我想把这个功能设计成一个可调用的api接口,例如提供一个评论id,就可以去执行以上ai回复(如该评论已回复,则返回已回复内容)。请你保持上述代码不动的基础上修改
...
增强 API 响应
// 好的。现在我们来增强前端用户体验:目前执行ai回复时,前端不会有任何响应或提示,我的想法是可以先写入评论列表,显示等待响应(实际是否写入数据库,你来决定),等api响应后,再将实际返回结果写入前端评论。关于前端实现你不用管,把后端响应给我就行。

AI 反垃圾

这个想法是我在 obaby 那偶然看到的,当时就觉得这个思路特别新颖,现在刚好给评论系统接入AI了,正好试试效果。其实这个反垃圾的效果和接入的模式应该有很大关系,后面怕误判又把被AI判定的评论搞到后台列表手动审核了,这个测试还有很大的改进空间。

AI 评论过滤
// 我最近发现被刷了很多垃圾评论,刚好我们评论钩子中加入了AI系统,所以我想加入AI评论审核。新需求:在原有基础上,新增一个AI内容审核函数,这个函数主要通过用户提交的评论内容进行审查过滤,垃圾评论的规则可以参考数据库中被标定为“垃圾评论”的评论数据,进行自我学习和判定。

开这个AI助手用了几天时间,但实际开发成本很低,人工介入少,效果还好。现在,你可以在评论区尝试`@2BER`来获取你的专属AI回复啦!

所有更新已同步到github.

Valine 迁移

在Wordpress适配完2BER AI,想到现在还在用Valie的评论,虽然leancloud还有半年才关闭服务,想着干脆一次性迁移过去了事,反正之前都迁移实验过了,没啥问题。

之前提到,leancloud将于27年初关停baas服务,届时valine依存的后端储存服务就没了,再早之前(23年)也提前做过迁移预演,只是时隔数年,再打开那篇文章的时候,很多东西自己都看不太懂了😂… 有不少bug和错误,记得那年还去研究了sql的好多语法来实现,搞得既复杂效率又底下。

Leancloud 服务关停预告

Leancloud 服务关停预告

关服公告 昨天查看 leancloud 后台数据的时候,一条公告映入眼帘:LeanCloud 将于 2027 年 1 月 12 日停止对外提供服务,详情...

2BROEAR 16/01/2026 | 1633 views.

不过好在,我们还有AI!

一开始只是尝试着问下,他刚开始搜了下网上的通用转换脚本,发现没有,就自定义写了匹配(这里他自己拿到了objectId, nick, mail, link, comment, insertedAt, url(文章路径),rid(父评论的objectId),ua等)。

基础需求
// 你有什么好办法把valine.js.org的评论jsonl数据,迁移到wordpress中吗?评论数据需要关联文章id(valine用的url),关联父级评论,以及关联评论数量。

Python+SQL 批处理
// 我在windows环境,”请确保已安装 mysql-connector-python(或 pymysql)“,我现在有comment.jsonl,也有mysql数据库信息,给我一个windows只需你的脚本的步骤

AI给出的方案方便多了,本地Python脚本连接SQL远程数据库,全自动批量建立评论关联,插入wordpress数据库,一气呵成。虽然刚开始的方案不成熟,但几轮对话下来,很快便改进了实现方式。这里需要注意一点:如果他提供代码出问题了,要把全部报错信息和你的代码全部复制给AI。虽然AI支持长对话,但这样能最大程度减少隐形BUG出现。只要解题思路正确,AI能很快产出答案,但注意不用无脑复制粘贴,有时候AI会偷懒省略掉部分重复代码。还有,涉及到SQL数据部分,如果你开了 Memcached 缓存,记得清掉。

这里顺便贴一下Valine转Wordpress的Python脚本,AI会根据你的具体需求改进代码。注意,执行任何操作之前,先备份数据,使用这个脚本前需要告诉AI把脚本里的URL匹配模式改为你自己站点的URL结构。(PS:如果你没装python环境,可以先问下AI这段代码都需要装哪些运行环境。连接远程数据库需要开放数据库远程权限放行3306端口,操作完成后记得关闭。)

点此展开代码块
# 执行代码后,会根据你的数据量等待一段时间,完成后控制台输出迁移完成
import json
import re
import mysql.connector
from datetime import datetime, timezone
from urllib.parse import urlparse, unquote, quote

# ========== 配置(修改为你的信息) ==========
JSONL_FILE = "comment.jsonl"
DB_CONFIG = {
    "host": "你的数据库地址",
    "user": "数据库用户名",
    "password": "数据库密码",
    "database": "数据库名",
    "charset": "utf8mb4"
}
TABLE_PREFIX = "wp_"        # 你的表前缀
# =========================================

conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()

# 1. 确保 comment_content 是 LONGTEXT
try:
    cursor.execute(f"ALTER TABLE {TABLE_PREFIX}comments MODIFY comment_content LONGTEXT")
    print("comment_content 已改为 LONGTEXT")
except Exception as e:
    print("修改字段备注:", e)

# 2. 获取所有文章 slug -> ID
cursor.execute(
    f"SELECT ID, post_name FROM {TABLE_PREFIX}posts "
    f"WHERE post_type IN ('post','page') AND post_status='publish'"
)
rows = cursor.fetchall()
print(f"查询到 {len(rows)} 篇文章")

slug_to_id = {}
for post_id, post_name in rows:
    slug_to_id[post_name.lower()] = post_id

# 3. 生成候选 slug 列表的函数
def get_candidate_slugs(url_str):
    """
    从 Valine 的 URL 中提取可能的 slug 候选。
    1. 先取路径最后一段(原始 slug)
    2. 如果原始 slug 包含日期前缀(如 25-09-2019_),去掉前缀生成第二个候选
    返回候选 slug 列表,按优先级排序。
    """
    path = urlparse(url_str).path.strip("/")
    if not path:
        return []

    raw_slug = path.split("/")[-1]   # 最后一段
    # 统一解码并转小写(WP 风格)
    try:
        decoded = unquote(raw_slug)
        encoded = quote(decoded, safe='').lower()
    except:
        encoded = raw_slug.lower()

    candidates = [encoded]

    # 匹配形如 "DD-MM-YYYY_" 的前缀
    match = re.match(r"^\d{2}-\d{2}-\d{4}_(.+)", encoded)
    if match:
        candidates.append(match.group(1))  # 去掉日期前缀后的部分

    return candidates

# 4. 读取 JSONL 并分类
oid_to_new_id = {}
top_level, children = [], []
skipped_slugs = []

with open(JSONL_FILE, "r", encoding="utf-8") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        c = json.loads(line)

        candidates = get_candidate_slugs(c.get("url", ""))
        post_id = None
        for slug in candidates:
            post_id = slug_to_id.get(slug)
            if post_id:
                break

        if not post_id:
            skipped_slugs.append((c.get("url", ""), candidates))
            continue

        # ---------- 时间解析(使用 createdAt) ----------
        created_str = c.get("createdAt", "")
        try:
            if created_str.endswith("Z"):
                created_str = created_str[:-1] + "+00:00"
            dt = datetime.fromisoformat(created_str)
            # 统一存为 UTC 的 GMT 时间(WordPress 内部用 GMT)
            gmt = dt.strftime('%Y-%m-%d %H:%M:%S')
            local = dt.astimezone().strftime('%Y-%m-%d %H:%M:%S')  # 本地时间,按服务器时区自动转换
        except:
            now = datetime.now()
            gmt = now.strftime('%Y-%m-%d %H:%M:%S')
            local = gmt

        # ---------- user_id 判断 ----------
        user_id = 1 if c.get("mail", "").lower() == "xty@2broear.com" else 0

        comment = {
            "post_id": post_id,
            "author": c.get("nick", "")[:200],
            "email": c.get("mail", "")[:100],
            "url": c.get("link", "")[:200],
            "content": c.get("comment", "")[:200000],
            "date": local,
            "date_gmt": gmt,
            "approved": 1,
            "agent": c.get("ua", "")[:255],
            "oid": c.get("objectId"),
            "rid": c.get("rid", ""),
            "user_id": user_id
        }

        if not c.get("rid"):
            top_level.append(comment)
        else:
            children.append(comment)

# 5. 打印部分未匹配的样本,便于排查
if skipped_slugs:
    print(f"\n未匹配的评论数: {len(skipped_slugs)} 条")
    print("前 10 个未匹配示例:")
    for url, cands in skipped_slugs[:10]:
        print(f"  URL: {url}")
        print(f"  候选 slug: {cands}")
    print()

# 6. 插入数据库(加入 user_id)
insert_sql = (
    f"INSERT INTO {TABLE_PREFIX}comments "
    "(comment_post_ID, comment_author, comment_author_email, comment_author_url, "
    "comment_content, comment_date, comment_date_gmt, comment_approved, comment_agent, "
    "comment_parent, user_id) "
    "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, 0, %s)"
)

# 顶级评论
for t in top_level:
    data = (
        t["post_id"], t["author"], t["email"], t["url"],
        t["content"], t["date"], t["date_gmt"], t["approved"], t["agent"],
        t["user_id"]
    )
    cursor.execute(insert_sql, data)
    oid_to_new_id[t["oid"]] = cursor.lastrowid

# 子评论
for child in children:
    parent_id = oid_to_new_id.get(child["rid"], 0)
    data = (
        child["post_id"], child["author"], child["email"], child["url"],
        child["content"], child["date"], child["date_gmt"], child["approved"], child["agent"],
        child["user_id"]
    )
    cursor.execute(insert_sql, data)
    new_id = cursor.lastrowid
    oid_to_new_id[child["oid"]] = new_id
    if parent_id != 0:
        cursor.execute(
            f"UPDATE {TABLE_PREFIX}comments SET comment_parent = %s WHERE comment_ID = %s",
            (parent_id, new_id)
        )

# 7. 更新文章评论数
cursor.execute(
    f"UPDATE {TABLE_PREFIX}posts p "
    f"SET comment_count = (SELECT COUNT(*) FROM {TABLE_PREFIX}comments c "
    f"WHERE c.comment_post_ID = p.ID AND c.comment_approved = 1) "
    f"WHERE p.post_type IN ('post','page')"
)

conn.commit()
cursor.close()
conn.close()
print("迁移完成!")

小结

AI辅助开发的故事告一段落,短短时间就完成了两个任务标的。不得不说,这玩意有时候是真好用!

最后,感谢 Leancloud + Valine 一路陪伴,咱们江湖有缘再见!


评论留言

avatar
「 涂鸦画板 」 关闭表情 bilibili 小电视
h0h1h2h3h4h5h6h7h8h9h10h11h12h13h14h15h16h17h18h19h20h21h22h23h24h25h26h27h28h29h30h31h32h33h34h35h36h37h38h39h40h41h42h43h44h45h46h47h48h49h50h51h52h53h54h55h56h57h58h59h60h61h62h63
5 条评论
user_avatar
acevs Firefox / Windows 10
2026-06-29 回复
效果不错~
    user_avatar
    2broear adminSafari / Windows 10
    2026-06-29 回复
    @acevs , 嘿嘿,你说呢@2ber
    user_avatar
    2BER AI Comment #5900
    2026-06-29 回复
    @2broear , 嘻嘻,效果确实不错呢~ 😄 AI的加入让评论系统更智能,更有趣啦!🌟
user_avatar
2broear adminSafari / Windows 10
2026-06-29 回复
@2BER
    user_avatar
    2BER AI Comment #5893
    2026-06-29 回复
    @2broear , 这篇文章主要讲了两件事:一是作者更新了WordPress的评论系统,增加了一个名为@2BER的AI助手来增强评论互动,这个AI助手能自动回复用户评论,支持文章摘要等功能;二是作者将Valine评论系统的数据迁移到了WordPress,因为Valine即将关闭服务。文章还提到了AI在开发过程中的高效性和在反垃圾评论方面的应用。最后,作者分享了一个Python脚本,用于将Valine的评论数据迁移到WordPress数据库中。嘿嘿~