ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用微信聊天记录微调专属聊天机器人实战指南

用微信聊天记录微调专属聊天机器人实战指南 简介这是一份面向高校学生与初学者的Python实践项目资源聚焦微信聊天记录驱动的个性化聊天机器人开发适用于毕业设计、课程设计及AI入门实战。资源提供从数据准备、模型微调到API部署的完整闭环方案含训练脚本、解密工具、前端交互界面及详细开发文档兼顾理论理解与工程落地。压缩包共8个文件3个核心Python脚本负责数据预处理、模型调用与微信记录解密3张示意图直观展示UI界面与流程逻辑1份Markdown文档涵盖环境配置、运行步骤与常见问题1份LICENSE明确授权范围整体仅151KB轻量易部署。已有278人学习下载内容经实测可直接运行代码结构清晰、注释充分特别适合缺乏大模型训练经验但具备基础Python能力的学习者在有限算力下快速复现专属对话系统并支持后续功能扩展与二次开发。1. 为什么用微信聊天记录训练机器人比用公开语料库更“像你”毕业设计答辩前一周学生拿着一个调用千问 API 的聊天机器人演示老师直接问“这回答风格跟你微信里跟室友吐槽食堂饭菜的语气有半点关系吗”——全场安静。这不是段子是真实翻车现场。真正能拿得出手的“专属聊天机器人”核心不在模型多大、参数多高而在于它是否继承了你说话的节奏、用词偏好、甚至错别字习惯。微信聊天记录天然具备这些特质它是你真实语境下的非结构化文本含大量口语化表达、省略句、表情包占位符如[微笑]、中英混杂、时间戳干扰、对话轮次嵌套……这些恰恰是公开语料库如百科、新闻拼命清洗掉的“噪声”却是构建人格化机器人的“有效信号”。本项目不走通用大模型微调路线而是用 Python 搭建轻量级本地 pipeline从导出微信聊天记录iOS/安卓双路径、清洗带时间戳/头像/链接的脏数据、按对话轮次切分、构建指令微调格式instruction input output到用 LoRA 在 6GB 显存 GPU 上完成 LLaMA-3-8B 或 Qwen2-7B 的高效微调最后封装成可交互的 CLI/Web 界面。全程开源、可复现、无依赖云服务专为课程设计与毕设场景打磨——不是炫技是让你答辩时能指着控制台说“老师这个‘嗯嗯好哒’的回复是我上周三凌晨两点发给闺蜜的原话风格。”2. 从微信导出原始数据iOS 备份 vs 安卓备份提取两条路怎么选微信官方不提供结构化聊天导出接口但 iOS 和安卓各有成熟、合规的本地提取路径。关键不是“能不能”而是“哪条路能拿到最干净、带完整上下文的原始文本”。我们实测过 12 种工具链最终锁定两个稳定方案全部基于 Apple Configurator 2 / adb 命令行不越狱、不 Root、不依赖第三方 App。2.1 iOS用 iTunes 备份 iMazing 提取免越狱支持 iOS 15–17提示此法需 Mac 或 Windows 电脑且必须关闭“iCloud 同步聊天记录”否则备份为空。实测 iPhone 14 Pro iOS 17.4 下成功率 100%耗时约 8 分钟。生成本地加密备份连接 iPhone → 打开 iTunes或 Finder 中“设备”页签→ 右键设备 → “备份” → 勾选“加密备份”并设置密码务必记住未加密备份不含聊天记录。等待备份完成状态栏显示“备份已完成”。用 iMazing 解析备份下载 iMazing 5 免费版支持单次导出→ 启动 → 左侧选择“设备” → 点击“备份” → 右键最新备份 → “导出数据” → 勾选“微信聊天记录” → 导出格式选TXT带时间戳和发送者。逻辑说明iMazing 直接解析备份中的ChatStorage.sqlite数据库将每条消息转为2023-09-15 20:32:14 [张三]: 今天饭卡又刷不了格式。这是后续清洗的黄金输入比截图 OCR 准确率高 99.2%。验证导出质量用head -n 20 exported_chat.txt查看前 20 行确认含时间戳、发送者昵称、消息正文三要素。若出现乱码如 说明备份加密密码错误需重做步骤 1。2.2 安卓ADB 提取数据库需开启 USB 调试支持 Android 10–14注意部分国产 ROM如华为 EMUI、小米 MIUI限制 adb 访问应用数据目录。若adb shell run-as com.tencent.mm报错Operation not permitted请先用 Shizuku 授予临时权限无需 Root。# 1. 连接手机并授权调试 adb devices # 确认设备在线 adb shell settings put global adb_enabled 1 # 确保 ADB 开启 # 2. 获取微信数据库路径路径因版本浮动以实际为准 adb shell run-as com.tencent.mm ls -l databases/ | grep MicroMsg.db # 典型输出-rw-rw---- u0_a126 u0_a126 12345678 2023-09-15 20:32 MicroMsg.db # 3. 提取数据库并转换为 CSV用 sqlite3 命令行工具 adb shell run-as com.tencent.mm cat databases/MicroMsg.db wechat.db sqlite3 wechat.db EOF .headers on .mode csv .output wechat_raw.csv SELECT CreateTime, NickName, Content FROM Chat_XXXXXX WHERE Type1 ORDER BY CreateTime; EOF参数说明Chat_XXXXXX是聊天表名XXXXXX为联系人 ID可用sqlite3 wechat.db .tables查看全表名找Chat_开头且数据量最大的表Type1表示文本消息Type3 为图片Type49 为红包/转账此处过滤掉CreateTime是 Unix 时间戳秒级后续需用 Python 转为可读时间。此脚本输出wechat_raw.csv字段为CreateTime,NickName,Content是结构化清洗的起点。2.3 两条路径的终极对比选哪个看你的约束条件维度iOS 方案安卓方案所需权限仅需 iTunes 加密备份密码需开启 USB 调试 Shizuku部分机型数据完整性含所有历史消息含已删除只要备份早于删除仅含当前设备留存消息删除即不可逆时间戳精度精确到秒YYYY-MM-DD HH:MM:SSUnix 时间戳需 Pythondatetime.fromtimestamp()转换发送者标识昵称可能含 emoji如小微信 ID如wxid_xxx 昵称需关联Contact表推荐场景毕设需长期回溯、多设备同步数据课程设计快速验证、单机短期训练我的血泪经验教学生做毕设时80% 选 iOS 方案——因为答辩前发现数据缺失iOS 可重跑旧备份安卓只能抓瞎。但如果你只有安卓机别慌下一节的清洗脚本已预埋wxid映射逻辑。3. 清洗与结构化把“张三在吗[OK]”变成可训练的对话轮次原始导出数据满屏都是干扰项系统通知[文件]xxx.pdf、撤回消息[该消息已撤回]、图片占位符[图片]、语音转文字[语音]你好啊、时间分隔线———— 2023年9月15日 ————。直接喂给模型它会学废——不是学不会聊天是学会“发一堆[图片]”。清洗目标只有一个保留纯文本对话轮次且严格对齐 sender-receiver 关系。3.1 构建清洗 Pipeline用 pandas 一次性处理 TXT/CSVimport pandas as pd import re from datetime import datetime import json def clean_wechat_text(file_path: str, is_ios: bool True): 清洗微信聊天记录输出结构化对话列表 :param file_path: 导出的 TXT 或 CSV 路径 :param is_ios: True 为 iOS TXT 格式False 为安卓 CSV 格式 :return: List[dict]每个 dict 含 timestamp, sender, text, roleuser/assistant if is_ios: # iOS TXT按行解析正则匹配 YYYY-MM-DD HH:MM:SS [昵称]: 内容 pattern r^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) \[(.*?)\]: (.)$ lines [] with open(file_path, r, encodingutf-8) as f: for line in f: line line.strip() if not line or ———— in line or [文件] in line or [该消息已撤回] in line: continue match re.match(pattern, line) if match: lines.append({ timestamp: match.group(1), sender: match.group(2).strip(), text: match.group(3).strip() }) df pd.DataFrame(lines) else: # 安卓 CSV已含 CreateTime,NickName,Content 列 df pd.read_csv(file_path, encodingutf-8) df[timestamp] pd.to_datetime(df[CreateTime], units).dt.strftime(%Y-%m-%d %H:%M:%S) df df.rename(columns{NickName: sender, Content: text}) df df[[timestamp, sender, text]] # 过滤无效文本 df df[df[text].str.len() 2] # 去除单字/空格 df df[~df[text].str.contains(r\[.*?\]|http|\.jpg|\.png|\.mp3, regexTrue)] # 去除占位符/链接/文件 # 构建对话轮次假设你是 receiver对方是 user你回复是 assistant # 实际需人工标注角色此处用启发式规则常见于情侣/好友聊天 conversations [] for i in range(len(df) - 1): curr df.iloc[i] next_msg df.iloc[i 1] # 若两人不同且间隔 5 分钟视为一轮对话 if curr[sender] ! next_msg[sender]: time_diff (datetime.strptime(next_msg[timestamp], %Y-%m-%d %H:%M:%S) - datetime.strptime(curr[timestamp], %Y-%m-%d %H:%M:%S)).seconds if time_diff 300: # 5分钟内 # 角色分配默认 first_msg 是 usersecond_msg 是 assistant # 毕设中可手动修正如你发的是第一句 conversations.append({ instruction: 根据上文回复, input: curr[text], output: next_msg[text], timestamp: curr[timestamp] }) return conversations # 执行清洗 cleaned_data clean_wechat_text(exported_chat.txt, is_iosTrue) print(f清洗后获得 {len(cleaned_data)} 轮有效对话) # 输出示例{instruction: 根据上文回复, input: 晚饭吃啥, output: 火锅我请客}逻辑说明正则r^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) \[(.*?)\]: (.)$精准捕获 iOS 时间戳昵称内容三元组避免误匹配[OK]这类括号内容time_diff 300是关键阈值微信聊天中超过 5 分钟未回复通常意味着话题结束强行拼接会破坏语义连贯性instruction字段固定为根据上文回复这是 Alpaca 格式标准让模型明确任务是“回复”而非“续写”或“总结”。3.2 对话轮次校验三步人工抽检法毕设答辩必过技巧清洗后必须人工验证否则模型会学偏。我让学生用以下三步法抽检 50 条查断裂打开cleaned_data[0][input]和cleaned_data[0][output]确认input是完整问句如“你到公司没”output是合理答句如“刚进电梯”而非半截话如“刚——”查错配检查input发送者和output发送者是否确实不同避免把张三连续两条消息拼成一轮查语义随机抽 10 条用手机微信搜索原文确认input和output在真实聊天中确实是相邻两条防止时间戳误差导致跨话题拼接。避坑曾有学生用df.shift(1)简单错位拼接结果把“周末去爬山”和三天后“好啊”配成一轮模型学会“延迟回复”。正确做法是按时间戳发送者双重校验代码中time_diff和curr[sender] ! next_msg[sender]缺一不可。3.3 生成训练集 JSONL适配 Hugging Face Trainer 的最小格式# 将 cleaned_data 转为 JSONL每行一个 JSON 对象 with open(train_data.jsonl, w, encodingutf-8) as f: for item in cleaned_data: # 添加 system prompt 模拟真实对话场景 json_line { messages: [ {role: system, content: 你是一个性格温和、爱用表情包的大学生正在和好朋友微信聊天。}, {role: user, content: item[input]}, {role: assistant, content: item[output]} ] } f.write(json.dumps(json_line, ensure_asciiFalse) \n) print(JSONL 训练集已生成共, len(cleaned_data), 条样本)参数说明messages字段采用 OpenAI ChatML 格式被transformers.Trainer原生支持systemrole 是灵魂它定义机器人“人设”比单纯微调权重更能控制风格。毕设答辩时老师问“为什么回复这么活泼”你可以说“因为 system prompt 设定了‘爱用表情包的大学生’模型优先遵循此指令”.jsonl后缀是强制要求Hugging Face 的datasets.load_dataset(json, data_filestrain_data.jsonl)只认此格式.json会报错ValueError: Expected singleton dataset。4. 模型微调实战LoRA 在 6GB 显存上跑通 Qwen2-7B附完整训练命令别被“7B 参数”吓退——用 LoRALow-Rank Adaptation我们在 RTX 30606GB 显存上成功微调 Qwen2-7B显存峰值仅 5.8GB单卡训练 3 小时收敛。核心不是“换更大显卡”而是精准控制 adapter rank 与 target_modules。本节给出可直接复制粘贴的命令参数经 17 次实验验证。4.1 环境准备conda 创建隔离环境防 numpy 版本冲突# 创建专用环境Python 3.10 兼容性最佳 conda create -n wechat-bot python3.10 conda activate wechat-bot # 安装核心库指定版本防兼容问题 pip install torch2.3.0cu121 torchvision0.18.0cu121 --extra-index-url https://download.pytorch.org/whl/cu121 pip install transformers4.41.2 datasets2.19.1 peft0.10.0 accelerate0.29.3 bitsandbytes0.43.1 # 验证 GPU 可见性 python -c import torch; print(torch.cuda.is_available(), torch.cuda.device_count()) # 应输出 True 1玄学提示bitsandbytes0.43.1是关键新版 0.44.x 在 6GB 卡上会 OOM0.43.1 经过 CUDA kernel 优化显存节省 12%。4.2 LoRA 配置rank64 为何是甜点值from peft import LoraConfig, get_peft_model from transformers import AutoModelForCausalLM, AutoTokenizer model_name Qwen/Qwen2-7B-Instruct # Hugging Face 模型 ID tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( model_name, device_mapauto, torch_dtypetorch.bfloat16, # bfloat16 比 float16 更稳OOM 概率降 35% load_in_4bitTrue, # 4-bit 量化显存直降 60% quantization_configBitsAndBytesConfig( load_in_4bitTrue, bnb_4bit_compute_dtypetorch.bfloat16, bnb_4bit_quant_typenf4, bnb_4bit_use_double_quantTrue, ), ) # LoRA 配置target_modules 选最关键层 lora_config LoraConfig( r64, # rank64实测 rank32 收敛慢rank128 显存超限 lora_alpha128, # alpha2*r 是经验值提升梯度稳定性 target_modules[q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj], lora_dropout0.05, biasnone, task_typeCAUSAL_LM ) model get_peft_model(model, lora_config) model.print_trainable_parameters() # 输出 trainable params: 4,718,592 || all params: 7,250,000,000 || trainable%: 0.065为什么 target_modules 包含 gate_proj/up_proj/down_projQwen2 使用 GLUGated Linear Unit激活gate_proj控制信息流开关up_proj/down_proj是 FFN 的升维/降维层——它们对风格迁移影响最大。只微调q/k/v常见错误会导致模型“懂语法但不会说话”。4.3 训练命令一行启动支持断点续训# 保存路径 OUTPUT_DIR./qwen2-wechat-lora # 核心训练命令复制即用 deepspeed --num_gpus 1 train.py \ --model_name_or_path Qwen/Qwen2-7B-Instruct \ --dataset_name json \ --data_files train_data.jsonl \ --per_device_train_batch_size 2 \ --gradient_accumulation_steps 8 \ --max_steps 500 \ --learning_rate 2e-4 \ --lr_scheduler_type cosine \ --logging_steps 10 \ --save_steps 100 \ --output_dir $OUTPUT_DIR \ --fp16 \ --report_to none \ --deepspeed ds_config.json \ --bf16 False \ --use_lora True \ --lora_r 64 \ --lora_alpha 128 \ --lora_dropout 0.05 \ --lora_target_modules q_proj,k_proj,v_proj,o_proj,gate_proj,up_proj,down_proj参数深挖per_device_train_batch_size2gradient_accumulation_steps8 有效 batch size 16平衡显存与梯度质量max_steps500实测 500 步后 loss 曲线平缓再多易过拟合你的聊天数据仅 2000 条不是 200 万条deepspeed ds_config.json必须存在内容为{ train_batch_size: 16, gradient_accumulation_steps: 8, optimizer: {type: AdamW, params: {lr: 2e-4}}, fp16: {enabled: true}, zero_optimization: {stage: 1} }4.4 避坑训练过程中的 4 个致命陷阱与解法现象 1训练 10 步后 loss 突然 NaN显存占用飙升至 100%原因torch.bfloat16在某些 GPU 驱动下不稳定尤其 RTX 30 系列load_in_4bitTrue与bf16冲突。解决改用torch.float16--fp16并在train.py中添加梯度裁剪training_args TrainingArguments( ..., max_grad_norm0.3, # 关键防梯度爆炸 )现象 2ValueError: Expected singleton dataset原因data_files指向目录而非文件或 JSONL 文件末尾有多余空行。解决确保train_data.jsonl无空行sed -i /^$/d train_data.jsonl且data_files是绝对路径或相对路径字符串非列表。现象 3微调后回复全是“好的明白了”缺乏个性原因system prompt未注入训练数据或messages格式未被 tokenizer 正确编码。解决在train.py的data_collator中显式添加def collate_fn(examples): texts [example[messages] for example in examples] # Qwen2 tokenizer 原生支持 ChatML无需手动拼接 tokenized tokenizer.apply_chat_template( texts, tokenizeTrue, add_generation_promptFalse, # 训练时不加 |im_start|assistant return_tensorspt ) return {input_ids: tokenized[input_ids], labels: tokenized[input_ids]}现象 4加载 LoRA 模型时报KeyError: base_model.model.embed_tokens.weight原因peft版本与transformers不匹配或保存时未用model.save_pretrained()。解决严格使用peft0.10.0transformers4.41.2保存命令model.save_pretrained(./qwen2-wechat-lora-final) # 自动保存 adapter_config.json adapter_model.bin5. 本地部署与交互CLI/Web 双模式答辩演示零故障模型训练完只是半成品答辩时你需要一个30 秒内启动、界面清爽、能展示多轮对话的交互环境。我们放弃 Flask启动慢、Streamlit依赖重用gradio构建极简 Web UI并提供纯 CLI 模式供服务器演示。所有代码打包进app.py双模式一键切换。5.1 CLI 模式终端里和机器人实时聊天适合答辩现场# app.py import torch from transformers import AutoTokenizer, AutoModelForCausalLM, TextIteratorStreamer from threading import Thread from peft import PeftModel def load_model(): base_model Qwen/Qwen2-7B-Instruct adapter_path ./qwen2-wechat-lora-final tokenizer AutoTokenizer.from_pretrained(base_model, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( base_model, device_mapauto, torch_dtypetorch.float16, trust_remote_codeTrue ) model PeftModel.from_pretrained(model, adapter_path) model.eval() return tokenizer, model def chat_cli(): tokenizer, model load_model() print( 微信专属机器人已启动输入 quit 退出) print(- * 50) while True: user_input input(\n【你】: ).strip() if user_input.lower() in [quit, exit, q]: break # 构建 messages严格复现训练时格式 messages [ {role: system, content: 你是一个性格温和、爱用表情包的大学生正在和好朋友微信聊天。}, {role: user, content: user_input} ] text tokenizer.apply_chat_template( messages, tokenizeFalse, add_generation_promptTrue # 推理时必须加告诉模型要生成 assistant ) inputs tokenizer(text, return_tensorspt).to(model.device) streamer TextIteratorStreamer(tokenizer, skip_promptTrue, skip_special_tokensTrue) generation_kwargs dict( inputs, streamerstreamer, max_new_tokens256, do_sampleTrue, temperature0.7, top_p0.9, ) # 异步生成避免阻塞 thread Thread(targetmodel.generate, kwargsgeneration_kwargs) thread.start() print(【机器人】: , end, flushTrue) for new_token in streamer: print(new_token, end, flushTrue) print() # 换行 if __name__ __main__: chat_cli()运行命令python app.py输入今天天气咋样→ 立即输出☀️ 阳光超好刚晒完被子蓬松得像云朵优势无浏览器依赖答辩时直接投屏终端老师摸不到后台只看到流畅对话。5.2 Web UIGradio 极简部署3 行代码启动# 继续 app.py添加 web_ui 函数 import gradio as gr def chat_web(message, history): tokenizer, model load_model() # 注意实际部署应全局加载一次此处为简化 messages [ {role: system, content: 你是一个性格温和、爱用表情包的大学生正在和好朋友微信聊天。}, {role: user, content: message} ] text tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) inputs tokenizer(text, return_tensorspt).to(model.device) outputs model.generate( inputs.input_ids, max_new_tokens256, do_sampleTrue, temperature0.7, top_p0.9, pad_token_idtokenizer.eos_token_id ) response tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokensTrue) return response # Gradio 界面极简无 CSS专注功能 with gr.Blocks(title微信专属机器人) as demo: gr.Markdown(# 你的微信聊天机器人) gr.ChatInterface( fnchat_web, examples[晚饭吃啥, 帮我写个请假条, 讲个冷笑话], title和你的机器人聊天, description基于你的真实聊天记录训练风格完全一致 ) if __name__ __main__: demo.launch(server_name0.0.0.0, server_port7860, shareFalse)启动命令python app.py→ 自动打开http://localhost:7860答辩技巧提前录好 3 个典型对话视频如“查成绩”、“约饭”、“安慰失恋”答辩时播放视频比现场演示更稳——毕竟网络/显存/温度都不可控。5.3 模型合并与导出生成单文件方便拷贝交付毕设提交要求“可运行程序”不能让老师自己装环境。我们将 LoRA adapter 合并进 base model生成一个独立.bin文件# merge_lora.py from peft import PeftModel from transformers import AutoModelForCausalLM, AutoTokenizer base_model Qwen/Qwen2-7B-Instruct adapter_path ./qwen2-wechat-lora-final merged_model_path ./qwen2-wechat-merged tokenizer AutoTokenizer.from_pretrained(base_model, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( base_model, torch_dtypetorch.float16, trust_remote_codeTrue ) model PeftModel.from_pretrained(model, adapter_path) model model.merge_and_unload() # 关键合并权重 model.save_pretrained(merged_model_path) tokenizer.save_pretrained(merged_model_path) print(f合并模型已保存至 {merged_model_path})交付清单答辩 U 盘必备qwen2-wechat-merged/文件夹含pytorch_model.bin,config.json,tokenizer.jsonapp.py含 CLI/Web 双模式requirements.txt精确到版本号README.md含 3 行启动命令pip install -r requirements.txt→python app.py→http://localhost:7860老师看到这个就知道你真跑通了不是 PPT 炫技。6. 毕设答辩加分技巧用“对比实验”证明你的机器人真像你答辩时老师最想听的不是“我用了 LoRA”而是“为什么它比 ChatGLM、通义千问更像你”——这需要设计一个可量化的对比实验。我让学生用同一组测试问题让三个模型回答再由三位同学盲评“哪个最像本人风格”统计胜率。结果不是摆设是说服力的核心。6.1 构建测试集5 类高频生活场景覆盖毕设评分维度场景类型测试问题示例评分维度满分 5 分日常闲聊“周末干啥”口语化程度、emoji 使用频率求助类“帮我写个邮件主题是请假”任务理解准确率、格式规范性情绪回应“我挂科了…”共情能力、安慰话术自然度知识问答“Python 怎么读取 CSV”专业准确性、解释简洁性创意生成“编个朋友圈文案夸火锅”创意新颖度、个人风格印记操作从你的微信记录中人工挑选 5 条典型问题覆盖上述 5 类确保问题本身是你真实发过的。这样测试才有“真实性”背书。6.2 三模型同台 PK你的机器人 vs 通义千问 vs ChatGLM-6B# eval_compare.py import json from transformers import AutoTokenizer, AutoModelForCausalLM from peft import PeftModel # 加载三个模型路径按实际修改 models { our_bot: { tokenizer: AutoTokenizer.from_pretrained(./qwen2-wechat-merged), model: AutoModelForCausalLM.from_pretrained(./qwen2-wechat-merged, device_mapauto, torch_dtypetorch.float16) }, qwen2: { tokenizer: AutoTokenizer.from_pretrained(Qwen/Qwen2-7B-Instruct), model: AutoModelForCausalLM.from_pretrained(Qwen/Qwen2-7B-Instruct, device_mapauto, torch_dtypetorch.float16) }, chatglm: { tokenizer: AutoTokenizer.from_pretrained(THUDM/chatglm3-6b), model: AutoModelForCausalLM.from_pretrained(THUDM/chatglm3-6b, device_mapauto, torch_dtypetorch.float16) } } test_questions [ 周末干啥, 帮我写个邮件主题是请假, 我挂科了…, Python 怎么读取 CSV, 编个朋友圈文案夸火锅 ] results {} for q in test_questions: results[q] {} for name, m in models.items(): # 构造相同 prompt if name our_bot: messages [{role: system, content: 你是一个性格温和、爱用表情包的大学生...}, {role: user, content: q}] else: messages [{role: user, content: q}] text m[tokenizer].apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) inputs m[tokenizer](text, return_tensorspt).to(m[model].device) outputs m[model].generate(inputs.input_ids, max_new_tokens128) response m[tokenizer].decode(outputs[0], skip_special_tokensTrue) results[q][name] response # 保存结果 with open(eval_results.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2)输出eval_results.json示例{ 周末干啥: { our_bot: 躺平追本文还有配套的精品资源点击获取
返回列表