做 QQ 群生意,引流其实不算什么,真正磨人的是后面那步——给账号估价。你得把好几个月甚至跨年的聊天记录从头翻到尾,拿 Excel 一行行记谁发了多少次、什么时段活跃、在群里是什么地位。有人全程潜水,有人天天带节奏,还有人平时不吭声,一开口就“刀到要害”。搞完一天眼睛都快瞎了,最怕的还是漏掉那种隐形大佬,白白亏一笔。
这种活其实不需要人肉数数。直接调用 Ollama 本地拉取并运行 Gemma-3:12b-it-qat 这类轻量大模型,配合一个简单的 Prompt 框架,让它一次性读完导出的群聊 HTML 或 JSON,按发言频次、互动强度、话题深度三个维度打分就行。下面这段 Python 脚本就是最常见的“采集-解析-评分”骨架,用 Pandas 做数据预处理,再通过 requests 把整理好的特征丢给模型推理接口:
import pandas as pd, requests, json
df = pd.read_json("group_msgs.json")
payload = {"model":"gemma-3:12b-it-qat","messages":[{"role":"user","content":"请根据以下对话记录,输出每位成员的活跃度 0-100 分,并给出理由\n"+df.to_json(orient="records")}]}
r = requests.post("http://localhost:11434/api/chat",data=json.dumps(payload),headers={"Content-Type":"application/json"})
print(r.json()["message"]["content"])
你会发现模型不仅数得比人快,还能把“水但有用”的消息识别出来——例如深夜有人发了条“懂的都懂”,后面跟了十几条回复,这位潜水员的权重就会被悄悄调高。这一步做完,已经把传统手工评估甩出两条街了。
让模型读懂几千条废话,Prompt 得这么拆
聊到这就得面对最实际的环节——怎么让模型真正理解你那些几千条废话连篇的群聊。别指望直接把原始文本扔进对话窗口,上下文长度再大也架不住表情包、@全体成员和“有人吗”的重复攻击。
我试过几种导出格式。QQ 自带的“导出聊天记录”能给一份 .html,但这东西结构松散,消息时间戳混在标签属性里,读起来折磨。后来换成写了个脚本来爬手机本地数据库,或者用群管工具直接拉 JSON——每条消息拆成 {sender, time, content, reply_to} 四个字段,干净很多。
Prompt 设计才是真坑。一开始我让它“分析活跃度”,模型给我回了七个“该成员发言较多”,毫无区分度。后来把任务拆成了三步:先让模型按时间窗口(早 8-11、晚 20-24、凌晨 0-5)统计发言密度,再要求它识别“被回复次数”和“话题扩散”信号——比如某个人发了条消息,后面半小时内有 5 个不同 ID 跟帖,权重就该加。最后我给了一个评分尺度:
请根据以下 JSON 格式的聊天记录,按三个维度对每位成员打分(0-10):
1. 发言频率:每条消息计 1 分,凌晨时段消息加权 *1.5
2. 互动影响:消息被直接回复的次数 + 由此引发的新话题数量
3. 角色倾向:是否经常作为“问题发起者”或“答疑终结者”,是则 +2
成员ID | 频率得分 | 互动得分 | 角色得分 | 总分
记录样本:[{"sender":"小明","time":"2025-03-12 23:45","content":"有没有人试过这个配置?","reply_to":""}, ...]
跑完第一批数据后,我发现有个 ID 叫“守夜人”的,白天零发言,凌晨 2-4 点刷了四十多条,每条回复都有 3-8 个跟帖。手动翻我肯定忽略这种夜猫子,但模型直接给他打到了 27 分(满分 30)。这种“不是高频,但每次都能点燃讨论”的角色,卖号时反而是溢价点——买号的人要的就是群里有这种能带话题的号。
别想着一次 Prompt 就完美。我调了四版,第一版漏掉了纯表情回复(有些群靠表情包交流,模型默认跳过),第二版把“引用之前的消息”算作了重复发言。加了一条指令:“若消息内容仅包含图片/表情,标记为‘图像消息’,仍计入频率但互动权重减半。”
最后个坑:模型会幻觉成员名。如果群昵称带特殊符号,比如 [vip]阿强 或 阿强(已退群),它可能自己编个“阿强”或“VIP阿强”。我在预处理阶段用正则把方括号、括号内后缀全洗掉,统一保留纯昵称部分,再传给模型。
这一套走下来,你手里就有了每个成员的活跃度画像:高频话痨、深夜刺客、话题引爆器、还有那种“一个月说三句但句句值钱”的隐形人。下一步,这些分数就能直接塞进报价公式了。
让 Agent 跑起来,但 token 不是自来水
有了前面那套“画像”做底,这一步我用一个轻量 Agent 把群里每个人挨个过一遍,让它不断调用大模型 API,给每个成员打出一份“活跃度评分”。
原始 JSON 一屏屏刷过去,最容易漏的是“同名不同人”和“同人不同名”。我在进入评分前先做一轮清洗:用正则把昵称里的 [vip]、(已退群) 这类装饰干掉,再把“引用转发”展开成可读文本;随后按 sender_id 聚合,生成 members.json,字段至少包含:唯一 ID、纯化昵称、入群时间、最近 N 天发言数。这样 Agent 每次只拿一个人的消息上下文,丢给模型时不会串台。
我不想写成重型流水线,于是把流程拆成两个小循环:外层遍历 members.json,内层把该成员近 7 天的消息切成三段(早 8-11、晚 20-24、凌晨 0-5),分别统计密度。Agent 的核心就是一段“稳定提示词 + 结构化输出约束”,每次都返回同一格式,后面才好合并。为了不把 token 当水喝,我把“图像/表情”统一压缩成占位符,只在计数时保留“有一条多媒体”这个事实,内容本身不放上下文。
def run_chat_evaluate(uid, messages):
# messages: 该成员近期消息,已经过滤掉系统通知
prompt = """你是一个群聊分析师。请根据以下消息,为发送者计算三个维度得分(0-10):
1) 发言频率:每条计 1;凌晨(0-5) *1.5;仅图片/表情仍计 1。
2) 互动影响:被直接回复次数;以及"话题扩散"次数(其发言后 30 分钟内,≥3 个不同 ID 跟帖)。
3) 角色倾向:是否常提问(+2)或常答疑(+2);最多各 +2。
输出严格 JSON:
{"uid":"xxx","nickname":"xxx","freq":0,"interact":0,"role":0,"total":0,"evidence":["..."]}"""
resp = openai.ChatCompletion.create(model="gpt-4", messages=[{"role":"user","content":prompt}], response_format={"type":"json_object"})
return resp.choices[0].message.content
外层循环我加了并发限制,控制在每秒 3-5 个请求,顺便把“失败重试”做成指数退避。遇到模型胡编的 nickname,就回滚到清洗后的 members[uid]["clean_name"],再写入结果。
最终总分不是简单相加,而是做了一个“场景加权”:白天高频=基础流量,晚间高密度=核心场,凌晨还能点燃讨论=稀缺。我把加权写死在汇总脚本里,而不是指望模型自己把握:
- 发言频率:w1=1.0;若凌晨占比>=30%,额外乘以 1.3
- 互动影响:被回复数 *0.6 + 话题扩散次数 *1.2
- 角色倾向:提问者+1.5,答疑者+2.0(二者取高)
打完分,Agent 顺手吐出“证据摘要”:例如“昨晚 23:30 发起配置问题,后续 7 人跟进,形成 3 轮次讨论;凌晨 2-4 共 42 条,其中 9 条被引用回复”。这份摘要将来直接贴进报价单,买主一眼就能看懂“为什么他贵”。等这一车跑完,Excel 不再塞满“备注”,而是只剩两张表:高活跃名单,及其对应的可解释得分。
定价不能靠猜,得让每分钱都有来路
评分跑完了,证据摘要也吐了,接下来就是最敏感的部分——到底值多少钱。
起初我试过让大模型直接给一口价,结果它要么往高了瞎报(“此用户群内声望极高,建议定价2000元”),要么缩手缩脚给个50。关键是,你问它“为什么是这个数”,它回你一通车轱辘话。
这不行。定价必须拆成因子,每个因子都有来源,最终数字能倒推。
我把公式写死在 Python 脚本里,不交给模型瞎编:
def price_estimate(user):
base = 50 # 基础价,只要是活人
# 注册时长:每满一个月 +2,上限40
age_value = min(user["months_since_register"] * 2, 40)
# 群聊等级:群主/管理员 +30,元老(入群超1年) +15,普通0
role_value = {"owner": 30, "admin": 25, "elder": 15, "member": 0}[user["group_role"]]
# 活跃度总分(0-30) 映射为价格:每分折3元
activity_value = user["activity_score"] * 3
# 历史交易记录:如果有过成功交易+20,无记录0
trade_value = 20 if user["trade_history"] else 0
# 最终定价 = base + age_value + role_value + activity_value + trade_value
return base + age_value + role_value + activity_value + trade_value
每个因子的上限我都做了硬约束。比如注册时长最多折40元,因为老号不等于好号——我见过注册5年但期间0发言的僵尸。群主/管理员有额外溢价,但前提是近期确有管理行为(踢人、改群公告、发起群待办),否则只算元老不加权。
公式跑完,得到的是一个冷冰冰的数字——470。买家问“凭什么”,你不能丢给他一行代码。这时候大模型出场,但角色变了:不再是定价员,而是翻译官。
Prompt 长这样:
你是一个QQ账号评估报告撰写助手。给定以下结构化数据,
请生成一段200字以内的"定价理由",要求:
1. 用自然语言描述每个因子的贡献
2. 提及具体证据(来自评分阶段的"证据摘要")
3. 语气中性客观,不要吹嘘
输入:
{
"uid": "12345",
"nickname": "风间",
"base_price": 470,
"factors": {
"注册时长": {"value": 24, "detail": "入群24个月"},
"群聊角色": {"value": 25, "detail": "管理员,近30天执行过4次禁言"},
"活跃度评分": {"value": 27, "detail": "日均47条,凌晨占比34%"},
"历史交易": {"value": 20, "detail": "有1次出号记录,成交价300"}
},
"evidences": ["凌晨2点发起技术讨论,7人跟进", "被@次数日均3.2次"]
}
纯文本,第一句写总价,后面逐条解释。
实测输出效果:
风间账号建议定价470元。其中:注册时长2年贡献24元,群管理员身份(近月有管理动作)加25元,
活跃度评分27分(日均47条且凌晨活跃)折合27元,历史交易记录加20元。
特别说明:该成员常在凌晨引发技术讨论(证据:7人跟进),被@频率是群均值6倍,属于核心话题发起者。
这份理由直接粘贴进报价单的“备注”栏。买主看到的是“管理员身份+凌晨活跃+历史交易”,每一项都能对到群聊记录里的具体行为,而不是一个黑盒数字。
最后我写了个简单的模板,用 Jinja2 渲染,把上面生成的内容拼成一张表。表头是:昵称、UID、总价、定价因子拆解、定价理由。每行最后加一个“证据快照”按钮,点击后展开该成员最近7天的消息数折线图(用 Chart.js 在本地画,数据来自评分阶段存下的 daily_count)。
这套流程跑下来,从采集消息到出报价单,全程大概8分钟。最烦的反而不是模型,而是那个“注册时长”怎么算——QQ群没有公开的入群时间戳,我最后取的是该成员在群文件里最早的一条消息时间作为近似。不精确,但够用。
生成完报价单我盯着屏幕看了半分钟,心想这东西要是落在灰产手里还真挺吓人。算了,工具本身没善恶,看谁在用吧。
做到后面才发现,最掉链子的往往是“看起来不重要”的那几处。
聊天里真QQ号、手机号、订单截图一飘,模型很容易顺手就学进去了。我的做法是前置一层脱敏:在采集器里做一次正则替换,把 11 位 QQ 号、8 到 11 位手机号、常见邮箱格式统一换成 UID_ANONYM,昵称里的姓氏也打码。别把原始 json 直接喂给 LLM,改完再进 pipeline,省得模型把真实信息复述回输出。
几万条消息一股脑塞进去,成本飙升还容易丢焦点。我用固定时间窗切分:每 2,000 行一段,相邻段重叠 10%,再用 ollama pull 拉一个 8B 的小模型先做本地摘要,最后才交给主模型做意图与角色识别。上下文不够时,把“群画像”做成 RAG:把群规、常讨论话题、黑话词表塞进向量库,检索后当背景附在 prompt 前面,比硬塞整份聊天记录稳。
有人一天甩 300 个表情包纯属气氛组,也有人凌晨一句“需求评审能改吗”硬是把七个人拽起来干活。我把特征拆了三层:数量看发言密度,质量盯被@次数、线程跟进数、还有禁言和撤回的比例,权限就看管理员、群管助理、文件上传这些角色。只有三层都拿高分,才算得上“可卖”的核心号。倒是碰上过一个潜水员,平常见不着人,结果手里攥着稀有群头衔和老版本勋章——这种号溢价反倒厉害。
流程跑通了,别忘了给每一步留个“证据快照”——报价单要是没根没据的,回头客户一问就露馅。工具再顺手,细节上也得多盯两眼,别翻车。
评论