
1. 项目概述与核心价值你有没有想过如果有一天你的聊天记录能“活”过来变成一个能代表你说话、思考、甚至开玩笑的数字分身这听起来像是科幻电影里的情节但今天借助开源项目 WeClone这已经变成了一个可以亲手实现的工程。我最近花了大量时间深度体验了这个项目它本质上是一个端到端的解决方案让你能够利用自己与特定联系人比如密友、伴侣或家人的 Telegram 聊天记录来训练一个专属的大型语言模型LLM最终将这个模型部署成一个可以与你或他人互动的聊天机器人也就是你的“数字分身”。这个项目的核心价值在于它的完整性和实用性。它不像很多学术项目只停留在模型训练这一步而是覆盖了从数据导出、清洗、预处理到模型微调、效果测试再到最终部署到 Telegram、Discord 等真实聊天平台的完整链路。这意味着只要你有一台性能足够的电脑甚至云端服务器就能亲手创造一个带有你或他人“灵魂印记”的 AI 伙伴。无论是为了纪念一段珍贵的友谊创造一个永不掉线的“树洞”还是探索 AI 人格化的前沿技术WeClone 都提供了一个绝佳的实践入口。接下来我将以一个实践者的视角带你完整走一遍这个充满乐趣与挑战的旅程。2. 核心思路与方案选型解析2.1 为什么选择聊天记录作为数据源要创造一个逼真的数字分身数据的“真实性”和“丰富性”至关重要。相比从零开始编写角色设定Persona真实的聊天记录包含了最原汁原味的语言风格、用词习惯、表情包使用频率、话题偏好甚至打字错误。这些都是构成一个人数字身份的核心要素。WeClone 选择从即时通讯软件入手正是看中了这类数据的高频、真实和场景化特性。目前它率先支持了 Telegram因为 Telegram 提供了相对友好的官方数据导出功能JSON格式这为后续的数据解析和结构化处理扫清了障碍。2.2 技术栈选型背后的考量WeClone 的技术选型体现了当前开源 AI 领域的最佳实践组合旨在平衡效果、易用性和社区生态。基础模型Qwen2.5-VL-7B-Instruct项目默认选用通义千问的 7B 视觉语言模型。选择它有几个关键原因首先它是一个“多模态”模型原生支持图像理解这对于处理聊天记录中大量的表情包、截图至关重要能让数字分身具备“看图说话”的潜力。其次7B 参数量在消费级显卡如 RTX 4090, 24GB 显存上通过量化技术如 QLoRA进行微调是可行的降低了硬件门槛。最后Qwen 系列模型在中文社区有良好的口碑和丰富的微调经验可供参考。微调框架LLaMA FactoryWeClone 没有重复造轮子而是基于 LLaMA Factory 进行模型微调。这是一个明智的选择。LLaMA Factory 封装了包括全参数微调、LoRA、QLoRA 在内的多种高效微调方法并提供了统一的配置接口。这意味着 WeClone 可以专注于其核心的数据处理和部署逻辑而将最复杂的模型训练部分交给一个成熟、活跃的框架保证了训练的稳定性和前沿技术的可用性。部署桥梁AstrBot / LangBot模型训练好后如何让它“活”在真实的聊天软件里WeClone 选择了与现有的聊天机器人框架集成而非自己实现一套复杂的消息收发逻辑。AstrBot 和 LangBot 都是优秀的开源多平台聊天机器人框架支持 Telegram、Discord、Slack 等。WeClone 训练好的模型通过提供标准的 OpenAI API 兼容接口可以无缝接入这些框架。这种“专业分工”的架构让项目边界清晰用户也可以根据喜好选择不同的部署前端。注意这种架构也意味着最终数字分身的交互体验如响应速度、消息格式、菜单功能会受到所选机器人框架AstrBot/LangBot的限制和影响。2.3 隐私与安全设计的底层逻辑用个人聊天记录训练 AI隐私是头等大事。WeClone 在这方面做了多层设计本地化处理所有数据处理和训练都在你的本地机器或你控制的服务器上完成原始数据无需上传到任何第三方服务器。自动信息脱敏集成了 Microsoft Presidio 库自动识别并尝试移除聊天记录中的电话号码、邮箱、地址等敏感信息。这是一个很好的第一道防线。用户自定义过滤提供了blocked_words屏蔽词列表。你可以手动添加任何你想过滤的特定词汇、昵称或句子包含这些词的对话条目会被直接丢弃。风险警示与免责项目文档和启动时都有强烈的风险提示强调这是用于学习和研究的实验性项目并建议在部署时明确标识其为 AI 机器人。这些设计体现了开发者的责任感但作为使用者你仍需保持最高警惕。绝对不要用包含他人隐私或敏感信息的聊天记录进行训练除非已获得明确授权。3. 环境搭建与数据准备实操3.1 硬件与软件环境准备工欲善其事必先利其器。根据官方文档的 VRAM 估算表如果你想微调默认的 7B 模型使用 QLoRA 方法在 4-bit 精度下大约需要 6GB 显存。这意味着一张 RTX 3060 (12GB) 或 RTX 4060 Ti (16GB) 就能胜任。如果使用 2-bit 量化显存需求可降至 4GB但可能会影响模型效果。我的实践环境是一台搭载 RTX 4090 (24GB) 的工作站这为尝试更高精度的微调如 8-bit QLoRA或未来微调更大模型如 14B留出了空间。软件方面你需要CUDA 12.6: 这是运行 PyTorch 和现代 AI 框架的基石。确保你的 NVIDIA 驱动支持此版本。Python 3.12: 项目推荐使用此版本以获得最佳兼容性。包管理工具 uv: 这是一个新兴的、速度极快的 Python 包管理器和虚拟环境工具。用它来管理依赖能避免很多版本冲突的“玄学”问题。安装步骤非常清晰# 1. 克隆项目代码 git clone https://github.com/xming521/WeClone.git cd WeClone # 2. 使用 uv 创建虚拟环境强烈推荐与系统环境隔离 uv venv .venv --python3.12 # 3. 激活虚拟环境 # Linux/macOS source .venv/bin/activate # Windows .venv\Scripts\activate # 4. 安装项目核心依赖 uv pip install --group main -e .这里-e .参数是以“可编辑”模式安装意味着你对项目代码的修改会立即生效方便调试。3.2 获取与准备聊天数据这是整个流程中最需要耐心和细心的一步。数据质量直接决定了数字分身的“像不像”。实操步骤安装 Telegram Desktop从官网下载并安装。导出聊天记录在 Telegram Desktop 中打开你想要克隆的那个对话。点击右上角的三个点菜单选择“导出聊天记录”。关键设置格式务必选择JSON。这是 WeClone 能够解析的格式。媒体类型建议勾选“照片”。虽然目前视频和语音不支持但图片表情包、截图是重要的上下文信息模型可以学习其与文本的关联。范围可以选择导出全部历史记录或者特定时间范围。数据越多理论上效果越好但处理时间也更长。保存与整理导出后你会得到一个名为ChatExport_[日期时间]的文件夹。将其整个文件夹复制到 WeClone 项目目录下的./dataset/telegram/路径中。如果你要克隆多个人就把多个导出文件夹都放在这个telegram目录下。重要心得在导出前建议先在 Telegram 里浏览一下聊天记录手动删除或跳过那些包含极端隐私如身份证照片、详细住址、银行卡号或你不想让 AI 学习的敏感对话。虽然 Presidio 会过滤但它不是万能的。提前清理是第一道也是最重要的一道防线。3.3 模型下载与配置初始化接下来是下载基座模型和初始化配置。下载模型你可以通过 Hugging Face 网页下载或者用git lfs命令行。我推荐命令行更稳定。# 确保已安装 git-lfs git lfs install # 克隆模型到指定目录 git clone https://huggingface.co/Qwen/Qwen2.5-VL-7B-Instruct models/Qwen2.5-VL-7B-Instruct这个过程会下载约 15GB 的数据请确保网络通畅和磁盘空间充足。初始化配置项目通过一个settings.jsonc文件管理所有设置。首先复制模板cp examples/tg.template.jsonc settings.jsonc这个文件就是整个项目的“控制中心”从数据清洗规则到训练超参数再到部署设置都在这里调整。4. 数据预处理从原始记录到训练语料4.1 配置文件深度解析打开settings.jsonc我们需要关注数据预处理相关的几个核心部分{ // ... 其他配置 ... language: zh, // 对话主要语言影响分词和过滤规则 platform: telegram, include_type: [message, photo], // 包含的消息类型目前支持文本和图片 telegram_args: { my_id: 123456789, // !!! 必须修改你的 Telegram 用户 ID others_ids: [] // 可选指定只克隆某个联系人的对话 }, make_dataset_args: { max_length: 2048, // 单条训练样本的最大 token 长度 split: train,test, // 划分训练集和测试集 test_size: 0.1, // 测试集比例 system_template: 你是一个名叫{name}的AI助手请根据以下对话历史模仿{name}的语气和风格进行回复。, // 系统提示词模板 conversation_template: ### 历史对话:\n{history}\n\n### 当前查询:\n{query}\n\n### 回复: // 对话模板 }, blocked_words: [密码, 银行卡号后六位, 我家地址] // 自定义屏蔽词支持正则表达式 }telegram_args.my_id这是必须修改的一项。你需要找到自己在对话中的 ID。一个简单的方法是在导出的 JSON 文件里搜索你自己的用户名或电话号码找到对应的from_id字段那个数字就是你的 ID。填错会导致模型无法正确区分对话双方。make_dataset_args这部分决定了你的聊天记录如何被转换成模型能理解的训练样本。system_template和conversation_template定义了训练时的“上下文包装格式”对模型学习角色扮演至关重要。除非你很清楚自己在做什么否则建议先使用默认模板。blocked_words这是你的“终极隐私过滤器”。把任何你绝对不想出现在训练数据里的词或短语加进去。系统会删除整条包含这些词的对话。4.2 执行预处理与结果检查配置完成后运行预处理命令weclone-cli make-dataset这个过程会依次执行解析 JSON、按对话双方重组消息、应用隐私过滤器、按模板格式化、最后分割成训练集和测试集。实操现场记录与排查进度与日志命令行会输出处理进度包括读取了多少条消息过滤掉了多少条。务必仔细查看这些日志确认过滤规则是否按预期工作。输出文件处理完成后会在./dataset目录下生成dataset_info.json、train.json和test.json。用文本编辑器打开train.json的前几条看看检查格式是否正确敏感信息是否已被移除。常见问题处理速度慢如果聊天记录很大几十万条预处理可能会比较耗时。这是正常的。my_id错误如果发现生成的对话历史里角色混乱比如把你的话都算成对方说的那一定是my_id填错了。回去重新检查 JSON 文件。屏蔽词不生效检查blocked_words中的词是否完全匹配包括空格和标点。或者被屏蔽的对话可能以其他形式如引用、转发存在需要更复杂的处理规则。我的经验第一次运行时我建议先用一个很小的、不重要的聊天记录导出文件进行测试快速走完预处理流程确认所有配置无误后再处理真正的主力数据。这能节省大量排查时间。5. 模型微调赋予AI你的“灵魂”5.1 训练参数调优实战数据准备好后就进入最核心的模型微调环节。再次打开settings.jsonc找到train_sft_args部分这里面的每一个参数都可能影响最终效果。{ // ... 其他配置 ... train_sft_args: { stage: sft, do_train: true, model_name_or_path: ./models/Qwen2.5-VL-7B-Instruct, // 模型路径 template: qwen2.5-vl, // 模板必须与模型对应 finetuning_type: lora, // 微调方法推荐 lora 或 qlora lora_target: all, // 对哪些模型层应用 LoRA lora_rank: 64, // LoRA 秩影响参数量和效果通常 8-128 lora_dropout: 0.1, // Dropout 防止过拟合 per_device_train_batch_size: 2, // 每个 GPU 的批次大小 gradient_accumulation_steps: 4, // 梯度累积步数 learning_rate: 1e-4, // 学习率微调时通常较小 num_train_epochs: 3.0, // 训练轮数 max_grad_norm: 1.0, // 梯度裁剪 logging_steps: 10, // 日志打印间隔 save_steps: 500, // 模型保存间隔 warmup_steps: 100, // 学习率预热步数 fp16: true // 使用混合精度训练节省显存 } }关键参数解析与调优建议finetuning_type: 对于大多数消费级显卡用户lora(16-bit) 或qlora(4/8-bit) 是唯一的选择。qlora显存占用更小但可能会引入极轻微的精度损失。我使用 RTX 4090 测试了lora(16-bit)效果不错。per_device_train_batch_size和gradient_accumulation_steps: 这是控制显存使用的“阀门”。实际有效批次大小 per_device_train_batch_size * gradient_accumulation_steps。如果遇到 CUDA out of memory (OOM) 错误首先调小per_device_train_batch_size如从2调到1。如果调到头了还是 OOM再增大gradient_accumulation_steps如从4调到8但这会略微降低训练速度。我的设置是batch_size2, accumulation_steps4在 24GB 显存下很稳定。lora_rank: 这个值越大LoRA 可训练的参数量就越多模型能力越强但也更容易过拟合。对于学习聊天风格这种任务rank64或128是常见的起点。如果你的数据量很小比如只有几千条消息可以尝试降低到32或16以防止过拟合。num_train_epochs: 训练轮数。数据量不同最佳轮数差异很大。一个实用的方法是观察训练损失loss。通常 loss 会快速下降然后趋于平缓。当 loss 在连续多个 steps 内不再明显下降甚至开始在测试集上上升过拟合时就可以提前停止了。可以设置一个较大的 epoch 数如 5 或 10然后根据eval_steps的评估结果手动中断或使用早停early stopping回调如果框架支持。learning_rate: 微调学习率通常在 1e-5 到 1e-4 之间。太大的学习率可能导致训练不稳定loss 剧烈震荡太小则学习缓慢。可以从1e-4开始如果训练不稳定尝试5e-5或2e-5。5.2 启动训练与监控单 GPU 训练命令非常简单weclone-cli train-sft训练开始后控制台会打印日志包括当前 loss、学习率、训练进度等。更重要的监控方式是使用 TensorBoard如果启用或直接查看保存的日志文件。训练过程中的经验与坑点Loss 不下降如果训练了几百步 loss 依然很高且不下降首先检查数据预处理是否正确。可能是对话模板设置错误导致模型无法理解任务。其次检查学习率是否过小。过拟合迹象如果训练集 loss 持续下降但你在后续的webchat-demo测试中发现模型只会生硬地复述训练数据中的原话缺乏泛化能力这就是过拟合了。解决方案增加数据量、降低lora_rank、增加lora_dropout、减少num_train_epochs、或者使用更强大的数据增强但目前 WeClone 尚未内置此功能。显存溢出OOM这是最常见的问题。除了调整 batch size还可以尝试启用gradient_checkpointing在配置中搜索并设置为true用计算时间换显存空间。使用qlora并尝试更低的量化位数如 4-bit 甚至 2-bit。清理不必要的后台进程确保 PyTorch 能获取到所有可用显存。我的第一次训练用了约 2万条对话消息在 RTX 4090 上以lora_rank64训练了 3 个 epoch大约花了 6 个小时。训练结束后模型权重会保存在./sft目录下具体路径可在配置中修改。6. 效果测试与模型部署6.1 本地交互测试找到最佳“性格”训练完成后不要急于部署。先用内置的网页 Demo 和测试脚本看看你的数字分身“成色”如何。# 启动一个简单的网页聊天界面 weclone-cli webchat-demo这个界面会加载你刚训练好的模型。你可以在这里和它自由对话测试其回复是否符合预期。关键测试点基础事实性问一些只有你和对话对方才知道的事情但确保已脱敏看它是否能“回忆”起来。注意它并非真正的记忆而是从训练数据中匹配模式。语言风格它的用词、语气、句式和标点习惯像吗会不会用对方常用的表情符号文字版或口头禅一致性就同一个话题进行多轮对话看它的立场和说法是否前后一致。创造性问一个训练数据里没有的全新问题看它能否基于已学习的风格进行合理发挥而不是回答“我不知道”。在settings.jsonc的infer_args部分有两个至关重要的参数控制着模型的“创造性”和“确定性”temperature温度值越高如 0.9回复越随机、有创意但也可能胡言乱语越低如 0.1回复越确定、保守但也可能枯燥重复。对于数字分身我建议从 0.7 开始尝试。top_p核采样参数与 temperature 配合使用。通常设置为 0.9 左右。多调整几组temperature和top_p找到最像“真人”的那个组合。然后将这个组合更新到infer_args中供后续 API 服务使用。6.2 启动API服务测试满意后就可以启动正式的 API 服务了这是连接模型与聊天机器人框架的桥梁。weclone-cli server默认情况下服务会运行在http://127.0.0.1:8005并提供一个与 OpenAI API 兼容的/v1/chat/completions端点。你可以用 curl 或 Postman 测试一下curl http://127.0.0.1:8005/v1/chat/completions \ -H Content-Type: application/json \ -d { model: gpt-3.5-turbo, messages: [{role: user, content: 你好你是谁}], temperature: 0.7 }如果收到一个 JSON 格式的回复说明 API 服务运行正常。6.3 集成到聊天机器人框架以 AstrBot 为例这里我以 AstrBot 为例因为它部署相对简单。假设你已经通过 Docker 部署好了 AstrBot。在 AstrBot 中添加平台在 AstrBot 管理界面添加 Telegram Bot或其他你想要的平台并按照指引配置好 Bot Token。添加模型服务商在 AstrBot 的“模型服务商”或“供应商”页面添加一个新的服务商。类型选择OpenAI。API Base URL填写你的 WeClone API 地址。这里是关键如果 AstrBot 和 WeClone 都运行在同一个 Docker 宿主机上你需要使用宿主机的 IP 或 Docker 内部网络地址而不是127.0.0.1。例如如果使用 Docker 桥接网络可能是http://host.docker.internal:8005或http://172.17.0.1:8005具体取决于你的 Docker 网络配置。多花点时间调试这个连接这是部署中最常见的坑。模型名称任意填写如my-weclone。API Key由于 WeClone 的 API 是免鉴权的这里可以随便填一个非空字符串比如sk-weclone。配置对话流程在 AstrBot 的“对话流程”或“管道”配置中选择你刚添加的服务商和模型。关闭工具调用非常重要在 Telegram 里向你的 Bot 发送命令/tool off_all。因为微调后的模型不具备调用外部工具如搜索、计算的能力如果开启AstrBot 可能会优先尝试调用失败的工具导致你看不到模型的真实回复。设置系统提示词在 AstrBot 的 Bot 设置中找到系统提示词System Prompt配置填入你在make_dataset_args中使用的system_template内容。这能帮助模型更好地进入角色。完成以上步骤后你就可以在 Telegram 里和你的数字分身对话了第一次回复可能会比较慢因为模型需要加载到显存中。7. 常见问题、排查技巧与进阶思考7.1 问题速查与解决方案问题现象可能原因排查步骤与解决方案训练时 CUDA Out of Memory1. 批次大小过大2. 模型或参数过大3. 其他进程占用显存1. 降低per_device_train_batch_size2. 增大gradient_accumulation_steps3. 启用gradient_checkpointing: true4. 换用finetuning_type: qlora并降低量化位数如45. 运行nvidia-smi关闭不必要的 GPU 进程API 服务启动失败或无法连接1. 端口被占用2. 模型路径错误3. 依赖库冲突1. 检查8005端口是否被其他程序占用可在settings.jsonc中修改api_server_args.port2. 确认model_name_or_path路径下的模型文件完整3. 在干净的虚拟环境中重新安装依赖uv pip install --group main -e .AstrBot/LangBot 无法收到回复1. API 地址配置错误最常见2. 工具调用未关闭3. 系统提示词不匹配1.重点排查在 AstrBot 宿主机上执行curl http://API地址:8005/v1/chat/completions ...测试连通性2. 在聊天平台向 Bot 发送/tool off_all3. 检查 AstrBot 中配置的系统提示词是否与训练时一致模型回复完全不像本人1. 训练数据不足或质量差2. 训练轮数不够或过多3.my_id设置错误4. 推理参数不合适1. 确保数据量足够建议 5000 条有效对话且已正确过滤噪音2. 尝试增加num_train_epochs或检查是否过拟合loss 不再下降3. 复核telegram_args.my_id4. 调整temperature(0.5-0.9) 和top_p(0.8-0.95)模型总是重复某些话1. 过拟合2.temperature设置过低1. 减少训练轮数增加lora_dropout或使用更多样化的数据2. 提高temperature值增加回复随机性预处理时大量消息被过滤1.blocked_words过于宽泛2. Presidio 误识别1. 检查blocked_words列表避免使用过于常见的词2. 查看预处理日志确认被过滤的具体原因。可考虑暂时关闭 Presidio如果数据已手动脱敏7.2 效果优化与进阶技巧数据质量 数据数量一万条高质量的、涉及多话题的对话比十万条“在吗”“吃了吗”的寒暄更有价值。在导出数据前可以有意选择那些能体现对方性格、观点和语言特色的对话时段。系统提示词工程system_template是引导模型的“第一指令”。除了默认模板你可以尝试更精细的设定例如“你正在模仿{name}的说话方式。{name}的性格特点是[活泼/沉稳/幽默]常用口头禅有[xxx, yyy]。请严格以{name}的身份和口吻回复不要承认自己是AI。” 这能更直接地塑造分身性格。混合数据训练如果你想让分身不仅像某人还能具备一些通用知识或技能可以尝试在训练数据中混合一些高质量的通用指令数据如 Alpaca 格式的数据。但要注意比例通用数据过多会稀释个性。多次迭代训练不要指望一次训练就达到完美效果。训练-测试-分析问题-调整数据或参数-再训练这是一个迭代过程。保存好每次训练的检查点checkpoint方便回滚和比较。7.3 关于隐私、伦理与未来玩转 WeClone 的同时我们必须清醒地认识到其边界。它生成的只是一个基于统计模式的“语言风格模仿器”并非真正的意识或记忆。在部署使用时务必遵循项目建议明确标识其 AI 身份避免用于欺骗或误导他人。从技术角度看WeClone 代表了个人AI应用的一个有趣方向高度个性化、私有化、以用户数据为核心。它的路线图也令人期待例如对更多数据源微信、WhatsApp的支持、记忆功能的引入、以及思维链COT的加入都将让数字分身更加“智能”和“连贯”。我个人在实践中的体会是这个过程更像是一种数字时代的“情感手工艺”。你将一段段散落的对话通过代码和算力编织成一个可以互动的影子。它不完美有时会“胡言乱语”有时会“记忆错乱”但当它在某个瞬间用那种熟悉的语气说出只有你们之间才懂的梗时那种奇妙的感受或许就是技术带给我们的一种全新的纪念与陪伴的方式。最后一个小建议在一切开始之前不妨先和你想要克隆的对象聊一聊这个想法这或许会是一个更有趣的开端。