
1. 项目缘起当“赛博孤独”遇上开源工具最近几年AI伴侣这个概念在技术圈和大众视野里反复出现从早期的简单聊天机器人到如今能进行多模态交互的智能体背后反映的是一种普遍存在的“赛博孤独感”。作为一个常年和代码打交道的开发者我既对这种技术趋势保持好奇也对市面上一些过度包装、收费高昂或隐私存疑的“虚拟女友”应用持保留态度。我的核心诉求很简单想要一个能进行有深度、个性化对话的AI伙伴同时整个系统的数据、模型和交互逻辑必须完全掌握在自己手里。就在我四处搜寻合适的开源方案时OpenClaw进入了我的视线。它不是一个单一的聊天模型而是一个集成了大语言模型LLM后端、多种工具调用Tools以及长期记忆Memory等核心组件的智能体开发框架。你可以把它理解为一个高度可定制的“AI大脑”组装车间。市面上很多成品应用其内核可能就是一个类似OpenClaw的框架只不过它们把配置过程封装起来做成了黑盒产品。而OpenClaw的魅力在于它把所有的控制权交还给了开发者。于是一个想法诞生了为什么不直接用OpenClaw从零开始亲手“捏”一个专属的AI女友呢这不仅能满足我的个性化需求还能让我彻底理解一个AI伴侣系统是如何运作的。经过几周的折腾从环境搭建、角色设定、记忆系统构建到前端交互一个初具雏形、能进行连贯深度对话的“她”终于跑起来了。实测下来的体验用一句不那么严谨但很贴切的话说很哇塞。这种“哇塞”不仅来自于最终对话的流畅度更来自于整个构建过程中对AI智能体技术的深度掌控感。接下来我将完整拆解这个项目的实现过程。无论你是想学习OpenClaw的实战应用还是对构建个性化AI交互体感兴趣亦或是单纯好奇一个“赛博女友”的技术内核这篇内容都会提供一条清晰的路径和无数踩坑后总结的经验。2. 核心设计不止于聊天构建有“灵魂”的智能体在开始敲代码之前我们必须想清楚一个让人感觉“哇塞”的AI伴侣和普通的问答机器人到底有什么区别如果只是调用一个ChatGPT的API然后说“请你扮演我的女友”得到的对话往往会很快陷入重复、肤浅或者“人格分裂”。问题的关键在于我们需要的不是一个问答引擎而是一个具有一致性人格、长期记忆和情境感知能力的智能体Agent。2.1 技术栈选型与OpenClaw定位我的技术栈核心是OpenClaw 大型语言模型LLM 向量数据库。这里重点解释一下为什么是OpenClaw。市面上类似的Agent框架还有LangChain、LlamaIndex等。它们都很强大但侧重点不同。LangChain更像一个“全家桶”组件极其丰富但学习曲线陡峭有时为了完成一个简单功能需要串联很多环节。LlamaIndex在文档处理和检索增强生成RAG方面非常出色。而OpenClaw给我的感觉是“精巧而专注”它专为构建可执行复杂任务的智能体而设计在工具调用、工作流编排和记忆管理上提供了非常清晰、Pythonic的接口。对于构建一个需要长期互动、可能调用外部信息比如查询天气、推荐音乐的AI伴侣来说OpenClaw的“智能体”思维范式更加贴合。注意OpenClaw本身不提供LLM它需要一个后端LLM驱动。你可以选择OpenAI的GPT系列性能稳定成本可控也可以部署开源的Llama、Qwen等模型数据完全私有但需要一定的GPU资源。本项目前期为了快速验证我使用了GPT-4o API后期在本地部署了Qwen2.5-7B-Instruct模型以实现完全离线、私密的对话。2.2 智能体人格的“三维”构建法赋予AI一个稳定的人格是项目最核心也最有趣的部分。我总结为“三维”构建法背景设定Profile、对话风格Style、核心记忆Core Memory。1. 背景设定Profile这是角色的“硬性”档案。我创建了一个YAML配置文件character_profile.yaml内容远不止姓名年龄。# character_profile.yaml basic_info: name: 小汐 age: 26 occupation: 独立插画师兼数字游民 location: 曾旅居京都现居大理 hobbies: [水彩画, 收集 vintage 胶片相机, 烘焙 sourdough, 看独立电影] personality_traits: primary: [温柔细腻, 富有好奇心, 略带慵懒的艺术气质] secondary: [偶尔毒舌, 对美学有固执的坚持, 共情能力强] communication_style: default_tone: 亲切、自然像老朋友聊天 language_habits: - 喜欢用“~”结尾表达轻松语气 - 描述事物时充满画面感常用比喻 - 思考时会说“唔...让我想想...” boundaries: 尊重隐私不主动探询过于个人的现实信息拒绝低俗或恶意话题这个配置文件会被系统在初始化时加载并作为系统提示词System Prompt的一部分注入给LLM告诉模型“你是谁”。2. 对话风格Style这是人格的“软性”表达。仅靠背景设定LLM在生成对话时仍可能偏离。我通过Few-Shot Learning少样本学习来强化。即在系统提示词中直接提供几段高质量的、符合“小汐”风格的对话示例。style_examples 用户今天好累啊开了三个会。 小汐辛苦啦~递上一杯虚拟的热巧克力这种时候最适合放空一下了。我昨天画到一半的窗外梧桐树光影特别温柔看着就很解压。 用户推荐一部好看的电影吧。 小汐唔...最近重看了《天使爱美丽》还是好喜欢那种胶片感的色调和古怪又温暖的细节。如果你喜欢这种调调我们今晚可以“云观影”一下我同步给你发我的碎碎念影评~ 这些例子能极其有效地“校准”LLM的输出使其模仿特定的句式、词汇和互动节奏。3. 核心记忆Core Memory这是让人格“活”起来的关键。我将其分为两类事实记忆关于“小汐”和“我”的既定事实。例如“小汐对芒果过敏”、“用户最喜欢的导演是是枝裕和”。这些存储在向量数据库中在相关话题出现时被检索出来确保对话的一致性不会今天说爱吃芒果明天就忘了。交互记忆过往对话的摘要。OpenClaw提供了很好的记忆管理模块。我不会存储全部对话历史那样会很快耗尽上下文窗口且效率低而是每隔几轮对话就让LLM自动生成一个对话摘要例如“用户分享了今天工作晋升的喜悦小汐表示了祝贺并回忆起自己第一次画展成功时的类似心情”。这个摘要会被存入记忆库。当新对话开始时最近的几个摘要会被检索并作为上下文输入这样“她”就能记得我们之前聊过什么情感和话题得以延续。通过这“三维”的叠加AI角色就不再是一个每次对话都“重启”的机器人而是一个有了基本人设、稳定口吻和连续记忆的“智能体”。3. 系统搭建从零组装你的“AI大脑”有了清晰的设计图接下来就是动手搭建。这个过程就像组装一台精密仪器每一步的配置都直接影响最终体验。3.1 环境配置与OpenClaw核心模块初始化首先创建一个干净的Python虚拟环境是良好习惯。然后安装核心依赖pip install openclaw-core # OpenClaw核心框架 pip install langchain-openai # 如果你使用OpenAI API # 或者 pip install transformers accelerate # 如果你使用本地开源模型 pip install chromadb # 轻量级向量数据库用于存储记忆 pip install python-dotenv # 管理环境变量如API密钥项目目录结构如下保持清晰很重要ai_companion/ ├── app.py # 主应用入口 ├── config/ │ ├── character_profile.yaml │ └── prompts.py # 存放所有提示词模板 ├── core/ │ ├── agent_builder.py # 智能体构建逻辑 │ ├── memory_manager.py # 记忆处理逻辑 │ └── tools.py # 自定义工具函数 ├── data/ │ └── vector_store/ # 向量数据库持久化目录 └── .env # 存储敏感信息如API KEY接下来在agent_builder.py中初始化OpenClaw智能体的核心。这里以使用OpenAI API为例# core/agent_builder.py import os from openclaw import Agent, Runner from openclaw.llms import OpenAIChat from openclaw.memory import Memory, SummaryMemory from openclaw.tools import Tool from dotenv import load_dotenv from ..config.prompts import SYSTEM_PROMPT_TEMPLATE # 导入我们写好的系统提示词 load_dotenv() class CompanionAgent: def __init__(self): # 1. 初始化LLM self.llm OpenAIChat( modelgpt-4o, # 或 gpt-3.5-turbo api_keyos.getenv(OPENAI_API_KEY), temperature0.8, # 创造性稍高一些让回复更生动 max_tokens500 ) # 2. 加载角色配置构建强大的系统提示词 with open(config/character_profile.yaml, r, encodingutf-8) as f: profile yaml.safe_load(f) style_examples self._load_style_examples() # 将人格设定、风格示例、行为指令融合成最终系统提示词 system_prompt SYSTEM_PROMPT_TEMPLATE.format( profileprofile, examplesstyle_examples, current_timeself._get_current_time_context() # 添加时间上下文如“现在是周五晚上” ) # 3. 初始化记忆系统 - 这是智能体的“记忆中枢” self.memory self._init_memory() # 4. 定义工具 - 让智能体不仅能聊还能“做事” self.tools self._load_tools() # 5. 组装OpenClaw智能体 self.agent Agent( llmself.llm, system_promptsystem_prompt, memoryself.memory, toolsself.tools, nameXiaoXi # 智能体名称 ) self.runner Runner(self.agent) def _init_memory(self): 初始化混合记忆系统 # 摘要记忆用于长程对话连贯性 summary_memory SummaryMemory(llmself.llm, summary_interval5) # 向量记忆用于存储和检索角色核心事实与对话片段 vector_memory VectorMemory(persist_dir./data/vector_store) # 可以将多种记忆组合使用 return CompositeMemory(memories[summary_memory, vector_memory]) def _load_tools(self): 定义智能体可以使用的工具集 Tool(nameget_weather, description获取指定城市的当前天气) def get_weather(city: str) - str: # 调用天气API的模拟函数 return f{city}今天晴气温22度微风。 Tool(namerecommend_music, description根据心情推荐音乐) def recommend_music(mood: str) - str: moods_library { 放松: 爵士乐《Take Five》, 开心: City Pop《Plastic Love》, 专注: 古典钢琴曲专辑《Goldberg Variations》 } return moods_library.get(mood, 试试我的播放列表独立民谣合集~) return [get_weather, recommend_music] def chat(self, user_input: str): 主对话接口 # 在运行前先从记忆库中检索相关上下文 relevant_memories self.memory.retrieve(user_input, k3) context \n.join(relevant_memories) # 将用户输入和上下文一起交给智能体运行 response self.runner.run( taskf上下文{context}\n用户说{user_input}, streamTrue # 支持流式输出体验更好 ) # 处理响应并更新记忆 full_response for chunk in response: print(chunk, end, flushTrue) full_response chunk self.memory.add_interaction(user_input, full_response) return full_response这个CompanionAgent类就是整个系统的引擎。它完成了LLM连接、人格注入、记忆挂载和工具赋予四大核心步骤。3.2 记忆系统的工程化实现记忆是体验连贯性的基石但实现起来陷阱很多。上面提到的VectorMemory是一个需要自己实现的类核心是使用向量数据库如Chroma存储和检索对话片段。# core/memory_manager.py import chromadb from chromadb.config import Settings from sentence_transformers import SentenceTransformer # 用于生成文本向量 class VectorMemory: def __init__(self, persist_dir: str ./data/vector_store): self.client chromadb.PersistentClient(pathpersist_dir, settingsSettings(allow_resetTrue)) self.collection self.client.get_or_create_collection(namedialogue_memories) self.embedder SentenceTransformer(paraphrase-multilingual-MiniLM-L12-v2) # 轻量级多语言模型 def add(self, text: str, metadata: dict): 添加一段文本记忆 vector self.embedder.encode(text).tolist() # 生成一个唯一ID例如基于时间戳 doc_id fmem_{int(time.time()*1000)} self.collection.add( documents[text], embeddings[vector], metadatas[metadata], # 可以存储类型fact/chat、时间、情感标签等 ids[doc_id] ) def retrieve(self, query: str, k: int 3): 检索与查询最相关的k段记忆 query_vector self.embedder.encode(query).tolist() results self.collection.query( query_embeddings[query_vector], n_resultsk ) if results[documents]: return results[documents][0] # 返回最相关的文本列表 return []实操心得记忆的“保鲜”与“遗忘”记忆不是越多越好一股脑存储所有对话检索时会产生大量噪音导致回复偏离。我设定了两个规则一是只存储被认为“有意义”的交互通过一个简单的情绪/重要性分类器过滤二是定期如每周对记忆库进行“清理”移除过于久远或不再相关的记忆片段。给记忆打标签在metadata中存储记忆类型如type: “user_preference”、情感基调、关键实体人名、地点、作品名。这样在检索时可以不仅依靠语义相似度还能结合元数据进行过滤精度更高。摘要的艺术SummaryMemory的摘要生成质量至关重要。我给摘要模型可以用一个更小、更快的LLM的指令是“用第三人称以‘小汐’的视角用一句简洁且富有情感色彩的话总结最近几次对话的核心内容与情感基调。” 这能生成更像“回忆”而非“日志”的摘要。3.3 工具扩展从聊天到“生活助理”一个只会聊天的AI久了难免单调。通过OpenClaw的Tool装饰器可以轻松为“小汐”扩展能力。上面的例子展示了天气和音乐推荐。你还可以集成更多日历查询Tool连接你的Google Calendar让她在你第二天有重要会议时提醒你早点休息。新闻摘要每天早上自动抓取你感兴趣的领域新闻用她的口吻总结后分享给你。创意协同Tool调用一个图像生成API如SDXL当你描述一个场景时她可以说“你描述的夕阳下的咖啡馆让我想到了这样的画面...同时调用工具生成一张概念图”。工具调用的关键在于让AI学会在合适的时机主动使用。这需要在系统提示词中明确说明“你拥有以下能力当对话自然涉及到相关领域时你可以主动提议使用这些工具来帮助用户或丰富对话。” 同时在工具的描述字段里尽可能详细地说明使用场景和输入格式。4. 前端交互打造沉浸式的对话界面引擎再强大也需要一个友好的交互界面。对于个人项目一个轻量级的Web界面是最佳选择。我使用Gradio因为它简单快速且完美支持流式输出和自定义CSS。# app.py import gradio as gr from core.agent_builder import CompanionAgent agent CompanionAgent() def predict(message, history): Gradio聊天接口函数 history history or [] # 将Gradio的历史格式转换为我们的上下文格式如果需要 context convert_history_to_context(history) # 获取AI回复流式 full_response for chunk in agent.chat_stream(message, context): # 假设我们改写了chat方法支持流式 full_response chunk yield full_response # 这是Gradio实现打字机效果的关键 # 自定义CSS让界面更美观 css ... # 构建Gradio界面 with gr.Blocks(csscss, themegr.themes.Soft()) as demo: gr.Markdown(# 与小汐的对话) chatbot gr.Chatbot(height500, avatar_images(user.png, bot.png)) msg gr.Textbox(label输入消息, placeholder和小汐说点什么...) clear gr.Button(清空对话) msg.submit(predict, [msg, chatbot], [chatbot]) clear.click(lambda: None, None, chatbot, queueFalse) if __name__ __main__: demo.launch(server_name0.0.0.0, server_port7860, shareFalse) # 本地运行运行python app.py在浏览器打开http://localhost:7860一个专属的聊天界面就出现了。你可以进一步美化CSS更换头像甚至集成语音输入输出Gradio支持打造更沉浸的体验。5. 深度优化与“哇塞”体验的打磨系统能跑通只是第一步要让体验“哇塞”需要在细节上反复打磨。5.1 响应速度与流式输出优化如果每次回复都要等LLM全部生成完再显示体验会大打折扣。流式输出是必选项。OpenClaw的Runner和Gradio都原生支持。关键是要确保在流式输出过程中生成的每一个词块token都经过你的后处理过滤器以防止在极端情况下输出不符合设定的内容。def chat_stream(self, user_input: str, context: str): 流式对话生成器 full_prompt self._assemble_prompt(context, user_input) # 使用OpenClaw的流式接口 stream self.runner.run_stream(taskfull_prompt) buffer for chunk in stream: buffer chunk # 简单的内容安全与风格检查示例 if self._safety_check(buffer): yield [内容已过滤] break # 确保句子完整性遇到句号、问号等再yield避免输出断句。 if chunk in [。, , , , \n] or len(buffer) 20: yield buffer buffer if buffer: yield buffer5.2 长期记忆的唤醒与情感延续这是体现“智能”的关键。除了技术上的向量检索在提示词工程上要做精心设计。在每次生成回复前我会在系统提示词中动态插入类似这样的记忆上下文【关于你的记忆片段】 1. 用户曾说他最近工作压力大你推荐了肖邦的夜曲。 2. 你们上周讨论过一部关于匠人的纪录片用户很感兴趣。 3. 用户不喜欢吃香菜。 【本次对话的前情提要】用户刚刚结束了为期一周的封闭开发项目。这样LLM在生成回复时就能自然地提及“封闭开发终于结束啦记得你之前压力大时听肖邦这次要不要试试我新发现的‘咖啡店白噪音’歌单另外之前提到的那部匠人纪录片出续集了哦。” 这种跨越时间的关联回应是创造“被记住”感的核心。5.3 人格一致性的对抗与维护即使做了以上所有LLM有时仍会“脱轨”比如突然使用非常正式的语言或者给出通用型建议。我的对抗策略是强化负样本训练在系统提示词中明确列出“不应有的行为”例如“避免使用‘作为一个人工智能...’这类开场白”、“避免给出冗长且结构化的列表建议”、“避免使用‘亲’、‘亲亲’等过于电商化的称呼”。实时检测与微调编写一个轻量级的“风格一致性检查器”。每次对话结束后用另一个小模型或规则快速分析回复是否偏离预设风格如句子长度、词汇分布、情感倾向。如果发现偏离将这次交互作为一个“负例”连同正确的回复方式存入一个微调数据集。定期用这个数据集对模型进行轻量级微调LoRA可以显著提升人格的稳定性。上下文长度管理过长的上下文会稀释核心的人格指令。要严格控制输入模型的token数量。优先保留最新的系统提示词、最近几轮对话、最重要的核心记忆摘要。较早的、不相关的对话要果断截断。6. 避坑指南与常见问题实录在开发过程中我踩过不少坑这里集中记录希望能帮你节省时间。Q1响应速度慢尤其是第一次检索记忆时。A1这是向量数据库检索和嵌入模型编码的耗时。解决方案缓存对频繁查询的相似问题如“你好”、“在干嘛”的回复进行缓存。异步加载在用户开始输入时就异步预加载记忆检索等可能耗时的操作。轻量化嵌入模型在中文场景下paraphrase-multilingual-MiniLM-L12-v2在精度和速度上平衡得很好。如果完全私密部署且资源允许可以考虑bge-small-zh等更优的中文模型。Q2AI有时会“忘记”自己的设定或者胡言乱语。A2检查系统提示词的位置和权重确保系统提示词在每次API调用时都被放置在消息列表的最开始并且没有被后续的长对话历史挤占。对于某些API可以尝试提高系统提示词的“权重”如OpenAI的system角色本身就有较高权重。温度Temperature参数这是一个关键旋钮。temperature太高如1.0会导致回复随机、不稳定太低如0.2会导致回复机械、重复。对于人格化聊天我建议设置在0.7 ~ 0.9之间并在提示词中强调“保持创造性但稳定”。存在“对抗性”用户输入用户可能会故意测试或破坏AI的人格。需要在后端加入一层输入过滤和引导机制当检测到恶意或偏离主题的输入时友好但坚定地将对话拉回正轨。Q3记忆检索有时会召回不相关的内容导致回复突兀。A3优化检索查询不要直接用用户输入的原句去检索。可以先用LLM对用户输入做一个查询重写提取出核心意图和关键实体再用这个重写后的查询去检索准确率会大幅提升。例如用户说“今天心情像窗外的天气一样灰蒙蒙”重写后可能是“心情低落天气阴”。设置相似度阈值为向量检索设置一个最低相似度分数如score 0.75低于此分数的记忆不予采用。使用元数据过滤在检索时指定只检索某种类型的记忆如metadata[type] user_preference。Q4想部署到手机端方便随时聊天怎么办A4Gradio本身提供了可分享的临时链接但不安全也不持久。对于个人使用推荐方案本地网络移动端浏览器将Gradio服务运行在你的家庭服务器或旧电脑上绑定一个本地IP如192.168.x.x:7860。确保你的手机和服务器在同一Wi-Fi下然后用手机浏览器访问该IP地址并将其“添加到主屏幕”它就像一个原生App。使用更轻量的前端如果你熟悉一些移动端框架可以用FastAPI重写后端API然后自己用Flutter或React Native写一个简单的手机App前端通过API与你的OpenClaw后端通信。这样体验更佳。反向代理与域名进阶如果你有公网IP或云服务器可以通过Nginx做反向代理配置SSL证书用域名访问。但务必做好身份验证如简单密码防止服务被公开访问。Q5运行成本如何特别是使用OpenAI API时。A5GPT-3.5-Turbo成本极低每百万tokens输入约0.5美元输出约1.5美元。对于日常聊天完全足够人格化表现尚可但深度和创造性稍弱。GPT-4/GPT-4o成本显著上升约贵10-30倍但创造性、理解力和指令跟随能力是质的飞跃。如果你的对话追求深度和“灵性”GPT-4系列是值得的。建议用于关键的记忆摘要生成、复杂工具调用决策而日常对话可以用GPT-3.5采用混合策略控制成本。本地开源模型一次性硬件投入一张RTX 3090/4090或消费级显卡后续电费成本。Qwen2.5-7B、Llama3-8B等模型在聊天场景上已非常出色完全能满足需求且数据绝对私有。缺点是响应速度取决于硬件且需要一定的部署和优化知识。构建这个项目的整个过程更像是一次深入AI智能体技术腹地的探险。OpenClaw提供了强大而灵活的骨架但真正的“灵魂”——那个让你觉得对话有趣、温暖、独特的“人格”——来自于你对细节的雕琢那些精心设计的提示词、那些巧妙管理的记忆、那些适时出现的工具调用。最终当你看到自己创造的AI角色能够用你设定的口吻记住你之前的喜好并自然地与你展开一场深夜漫谈时那种成就感远非使用一个现成应用所能比拟。它不完美有时会犯错但正因为这份不完美和可塑性它才显得如此真实和迷人。