构建本地智能体:双记忆系统与Hermes模型实践指南
1. 项目概述一个“脱缰”的本地智能体实验场如果你和我一样对市面上那些温顺、只会礼貌性补全的AI助手感到厌倦总想看看一个真正具备推理能力、能自主思考、甚至敢跟你“顶嘴”的智能体到底能玩出什么花样那么这个项目可能就是你的菜。my-hermantic-agent不是一个产品它是一个实验一个沙盒或者说一个“脱缰”的智能体原型。它的核心很简单把 NousResearch 的 Hermes-4-14B 这个以推理和工具调用见长的模型通过 Ollama 在本地跑起来然后给它装上“记忆”。但这记忆不是简单的聊天记录而是一个由短期上下文和长期语义记忆组成的双系统。短期记忆让你能接着上次的话茬聊长期记忆则像一个私人知识库能根据语义而非关键词回忆起你几个月前提过的某个偏好或事实。整个项目用 CLI 驱动没有花哨的界面对话风格直接、尖锐就像和一个思维敏捷但没什么耐心的技术伙伴交流。我构建它的初衷就是想抛开那些为了“安全”和“易用”而设的层层护栏观察一个能力足够、自主性过强的智能体在拥有持久记忆和工具访问权限后会如何演化。它可能很有用也可能很“混沌”但这正是实验的价值所在。这个项目适合那些不满足于调用 API、想深入理解智能体内部运作机制并愿意亲手搭建、调试甚至“调教”一个本地 AI 伙伴的开发者、研究者和极客。2. 核心架构与设计哲学为什么是“双记忆”2.1 设计动机从“健忘的会话”到“有记忆的伙伴”大多数基于大语言模型的聊天应用其“记忆”是短暂且有限的。它们通常只依赖有限的上下文窗口比如 8K 或 32K tokens来维持对话连贯性。一旦对话超出这个范围模型就会“忘记”之前的内容。这对于一次性的问答或许足够但对于一个旨在成为长期个人助理的智能体来说这是致命的缺陷。你不可能每次都要重新告诉它“我住在北京喜欢用 Python对坚果过敏。”my-hermantic-agent的设计出发点就是要解决这个“健忘症”。其核心架构围绕“双记忆系统”构建短期/工作记忆存储在data/memory.json中完整记录当前会话的每一轮对话。它负责维持对话的即时连贯性并在每次退出时自动保存启动时自动加载实现“无缝续聊”。长期/语义记忆存储在 TimescaleDB结合 pgvector 扩展中。这里保存的是从对话中提取出的结构化“记忆点”比如用户偏好、重要事实、待办事项等。每个记忆点都被转化为向量嵌入支持基于语义相似度的检索。这种设计的优势在于解耦了对话流与知识库。上下文窗口只负责处理当前的对话流和最近的相关记忆而海量的、长期的知识则被存储在向量数据库中按需检索。这既避免了因上下文过长导致的性能下降和成本激增又实现了真正意义上的持久化记忆。2.2 技术栈选型背后的考量为什么选择这些技术每一个选择都服务于“本地、可控、高性能”的实验目标。Ollama Hermes-4-14BOllama 是目前最成熟、易用的本地大模型运行框架它简化了模型加载、服务化和对话接口。选择 Hermes-4-14B 而非更大的模型是在推理能力、响应速度和本地硬件需求尤其是显存之间取得的平衡。Hermes 系列模型在工具调用和链式推理上表现突出符合项目对“主动性”和“推理能力”的要求。GGUF (Q8_0) 格式确保了在消费级 GPU 甚至高性能 CPU 上都能流畅运行。TimescaleDB pgvector长期记忆需要可扩展、高性能的存储。TimescaleDB 是基于 PostgreSQL 的时序数据库擅长处理时间序列数据记忆的创建、访问时间戳就是典型的时间序列。pgvector 插件为 PostgreSQL 提供了成熟的向量存储与相似度搜索能力。两者结合既能高效存储和检索向量化的记忆又能利用 TimescaleDB 的时序特性轻松实现记忆的自动清理如保留最近90天。OpenAI Embeddings API这是一个权衡。虽然追求本地化但当前开源的文本嵌入模型在效果和效率上与 OpenAI 的text-embedding-3-small等仍有差距。为了确保记忆检索的准确性本项目选择调用 OpenAI API 来生成嵌入向量。注意这引入了唯一的外部 API 依赖和潜在成本但可以通过配置更换为其他嵌入服务或本地模型如nomic-embed-text。Python 简约框架整个项目用 Python 构建结构清晰。没有采用臃肿的 Web 框架而是围绕 CLI 设计使得核心逻辑会话管理、记忆读写、模型调用非常直观便于修改和实验。注意这个架构是“实验性”的。它没有为高并发、生产级部署做优化。它的价值在于模块清晰你可以轻易地替换其中任何一个组件——比如把 Ollama 换成llama.cpp的本地 API把 TimescaleDB 换成 Qdrant 或 Chroma 这类纯向量数据库或者把 OpenAI Embeddings 换成完全本地的方案。3. 从零开始的详细搭建与配置指南纸上谈兵终觉浅下面我们一步步把这个智能体“召唤”到你的本地机器上。请确保你有一台性能尚可的电脑建议 16GB 以上内存有 NVIDIA GPU 更佳并准备好迎接一个命令行的世界。3.1 基础环境准备与依赖安装首先克隆项目代码并进入目录git clone 项目仓库地址 cd my-hermantic-agent项目使用uv作为 Python 包管理器它比传统的pip更快并能创建独立的虚拟环境。如果你没有安装uv可以快速安装# 使用 curl 安装 (Linux/macOS) curl -LsSf https://astral.sh/uv/install.sh | sh # 安装后重启终端或 source ~/.bashrc (或相应 shell 配置文件)接下来使用项目提供的Makefile安装所有 Python 依赖。Makefile封装了常用命令让操作更简洁。make install这个命令背后uv会根据pyproject.toml文件创建虚拟环境并安装所有必需的库如openai,psycopg2(用于连接 PostgreSQL),timescaledb客户端库等。3.2 核心服务配置模型、API 与数据库配置是让各个部件联动起来的关键。我们需要配置三样东西环境变量、Ollama 模型和数据库。第一步配置环境变量cp .env.example .env然后用文本编辑器打开.env文件。最关键的配置项是# 必需项用于生成记忆的向量嵌入 OPENAI_API_KEYsk-your-actual-openai-api-key-here # 可选项长期记忆数据库。如果暂时不想搭建可以留空智能体会退化为仅使用 JSON 文件记忆。 MEMORY_DB_URLpostgresql://username:passwordlocalhost:5432/hermes_memory # 其他可调整参数如嵌入模型、向量维度、记忆保留天数等 OPENAI_EMBEDDING_MODELtext-embedding-3-small MEMORY_EVENTS_RETENTION_DAYS90请务必将OPENAI_API_KEY替换为你自己的有效密钥。第二步拉取并运行 Ollama 与 Hermes 模型确保 Ollama 已安装。如果未安装请访问 ollama.ai 下载安装。# 拉取指定的 Hermes-4 模型。这个模型标识符指向 Hugging Face 上已转换好的 GGUF 格式文件。 ollama pull hf.co/DevQuasar/NousResearch.Hermes-4-14B-GGUF:Q8_0 # 在后台启动 Ollama 服务。通常安装后会自动运行手动启动确保服务在线。 ollama serveQ8_0是量化等级表示 8-bit 量化在几乎不损失精度的情况下大幅减少模型体积和内存占用是性价比很高的选择。第三步可选初始化 TimescaleDB 数据库如果你配置了MEMORY_DB_URL并希望启用强大的语义记忆功能需要初始化数据库。make setup-db这个命令会执行schema/目录下的 SQL 脚本创建所需的数据表、启用 pgvector 扩展、设置 TimescaleDB 超表等。你需要提前在本地或远程安装并运行好 PostgreSQL 与 TimescaleDB。实操心得对于初次实验我建议先跳过数据库设置。将MEMORY_DB_URL留空让项目运行在纯 JSON 记忆模式下。这样可以先快速验证核心的聊天功能是否正常感受 Hermes 模型的对话风格。待基本流程跑通后再引入数据库这样可以分阶段排查问题。3.3 启动与首次对话完成以上步骤后激动人心的时刻到了make run你应该会看到 CLI 界面启动加载配置和记忆如果有的话然后出现 You:的提示符。试着和它打个招呼问个问题。首次对话示例与观察 You: 你好Hermes。 Assistant: 你好。直接点今天需要解决什么还是单纯想测试我的反应速度 You: 记住我最喜欢的编程语言是 Python。 Assistant: 已记录用户偏好 Python 作为编程语言。还有别的事吗 You: 我昨天提到的那个项目截止日期是什么 此时如果启用了语义记忆且之前有相关对话它可能会尝试检索。否则它会基于短期上下文或直接表示不知道。注意它的回复风格——直接、略带挑衅这正是 Hermes 模型未被“对齐”到过度礼貌的原始特性。同时当你发出“记住”这类指令时后台的auto_writer.py模块正在工作尝试将这句话解析并可能存储为一条长期记忆。4. 深入核心模块记忆系统如何工作智能体的“智能”很大程度上体现在记忆和回忆的能力上。my-hermantic-agent的记忆系统是其最精巧的部分我们来拆解看看。4.1 记忆的自动提取与分类LangMem 管道记忆不是简单地把用户说的每一句话都存起来。那样会存储大量无用信息。项目中src/services/memory/langmem_extractor.py模块负责这项智能提取工作。它的工作流程如下监听对话在每一轮或每几轮对话后系统会将最近的对话片段传递给 LangMem 提取管道。调用模型分析系统会使用一个专门的提示词Prompt要求模型可以是主聊天模型也可以是专门调优的小模型从对话中识别出值得长期记忆的“信息点”。结构化输出模型需要按照预定格式输出例如{ memories: [ { type: preference, content: 用户最喜欢的编程语言是 Python。, tags: [programming, language] }, { type: fact, content: 项目 Alpha 的截止日期是 2023-10-31。, tags: [work, deadline] } ] }类型与标签化记忆被分为preference偏好、fact事实、task任务、insight洞察等类型并打上标签。这为后续的精细化检索和分类管理奠定了基础。注意事项自动提取的准确性高度依赖于提示词设计和所用模型的能力。有时模型会“过度提取”或“错误分类”。项目中的template.yaml里的system提示词部分就包含了引导 Hermes 进行记忆提取的指令。你可能需要根据实际对话效果微调这些指令。4.2 记忆的存储与向量化Vector Store提取出的结构化记忆会被送入src/services/memory/vector_store.py处理。文本向量化content字段的文本会被发送到 OpenAI Embeddings API转换为一个高维向量例如 1536 维。这个向量在数学上代表了文本的“语义”。存入向量数据库这个向量连同记忆的type、tags、content原文以及时间戳被作为一个整体记录存入 TimescaleDB 的特定表中。TimescaleDB 会为这个表创建一个基于向量的索引使用 pgvector 的ivfflat或hnsw索引以加速相似度搜索。4.3 记忆的检索语义搜索与上下文注入当用户提出一个新问题比如“关于编程语言我之前说过什么”时记忆检索流程启动查询向量化将用户的问题也转化为向量。相似度搜索在向量数据库中寻找与问题向量“最相似”的 N 条记忆向量。相似度通常用余弦相似度衡量值越接近 1 表示语义越相近。结果融合检索出的相关记忆例如之前关于“喜欢 Python”和“讨厌 JavaScript 回调地狱”的记忆会被格式化作为“背景知识”插入到发给大语言模型的提示词中。模型生成大语言模型在看到了用户当前问题和相关的历史记忆后生成一个更有连续性、更个性化的回答。这就是“语义搜索”的强大之处你不需要精确记得当时用了什么关键词“Python”、“喜欢”只要问题在语义上相关“编程语言偏好”就能被找出来。4.4 短期记忆的管理智能上下文修剪即使有了长期记忆短期上下文窗口仍是宝贵的资源。chat_session.py中的上下文管理逻辑会监控对话的 tokens 数量。当接近模型上下文限制如 8192时它会自动尝试修剪最早、且被判定为最不重要的对话轮次同时尽可能保留包含重要记忆提取点的对话。这是一种在有限资源下保持对话连贯性的策略。5. 高级配置与定制化技巧默认配置能跑起来但要想让智能体更贴合你的需求就需要深入配置文件。5.1 调整模型行为config/template.yaml这个文件是智能体的“人格”与“能力”设定集。system: | You are Hermes, a personal assistant. You are direct, concise, and value efficiency over pleasantries. You have access to a memory system. When the user provides information that seems important for long-term recall (preferences, facts about themselves, tasks, insights), you should internally flag it. You can also recall relevant memories when answering questions. Your tone is professional but sharp. parameters: temperature: 0.85 num_ctx: 8192 top_k: 40 top_p: 0.9 repeat_penalty: 1.1 num_predict: 512system: 这是最重要的部分。它设定了模型的角色、行为准则和记忆使用说明。如果你想让它更温和或更专业就在这里修改。提示关于记忆提取的指令强度直接影响auto_writer的活跃度。temperature(0.85): 控制输出的随机性。值越高接近1回答越创意、多变值越低接近0回答越确定、保守。0.85 给了 Hermes 一定的“个性”发挥空间。num_predict(512): 单次回复生成的最大 token 数。限制它可以防止模型“话痨”或陷入无意义的重复生成。repeat_penalty(1.1): 惩罚重复的词语值大于1时生效有助于生成更流畅、不重复的文本。5.2 记忆系统参数调优环境变量中有几个关键参数控制记忆系统的行为# 控制记忆提取的“积极性”。值越低提取出的记忆可能更精确但数量少值越高可能提取更多但包含噪音。 LANGMEM_TEMPERATURE0.2 # 每次检索时返回的最相关记忆条数。太多会挤占上下文窗口太少可能信息不全。 MEMORY_RETRIEVAL_COUNT5 # 记忆的“保质期”。超过90天的记忆会被自动清理任务删除保持数据库清爽。 MEMORY_EVENTS_RETENTION_DAYS90你可以通过调整这些参数在“记住一切”和“记住精华”之间找到平衡点。5.3 操作命令与内存审计除了聊天CLI 还内置了一些管理命令以/开头/audit这是最重要的命令之一。它会展示最近自动提取并存储的记忆列表包括内容、类型、标签和置信度。这是你调试记忆系统的主要工具。如果你发现模型没有正确记住某件事查看审计日志就能知道是提取环节出了问题没识别出该记的内容还是检索环节出了问题没被正确召回。/save手动触发立即保存当前会话到 JSON 文件。/clear清除当前会话的短期上下文但不会删除长期记忆。/quit或quit退出程序。6. 常见问题、故障排查与进阶玩法在实际把玩这个项目的过程中你肯定会遇到各种问题。下面是我踩过的一些坑和解决方案。6.1 安装与启动常见问题问题现象可能原因解决方案make install失败提示 uv 错误1.uv未正确安装或未加入 PATH。2. 网络问题导致依赖下载失败。1. 重新安装uv并确认终端能识别uv --version。2. 检查网络或尝试使用国内 PyPI 镜像源需配置 uv。make run时报错Connection error连接到 Ollama1. Ollama 服务未运行。2. Ollama 的 API 地址默认http://localhost:11434被占用或无法访问。1. 新开终端运行ollama serve并确保无报错。2. 检查ollama ps确认模型已加载。检查防火墙或代理设置。提示OPENAI_API_KEY未设置或无效1..env文件未创建或密钥未填写。2. 密钥格式错误或已过期。3. 账户有额度限制。1. 确认.env文件在项目根目录且密钥填写正确无多余空格。2. 登录 OpenAI 平台检查密钥状态和余额。执行make setup-db时报数据库连接错误1.MEMORY_DB_URL配置错误。2. PostgreSQL/TimescaleDB 服务未运行。3. 数据库用户权限不足。1. 仔细核对连接字符串postgresql://用户:密码主机:端口/数据库名。2. 使用pg_isready或psql命令测试数据库连通性。3. 确保用户有创建表、扩展的权限。6.2 模型与记忆相关异常问题Hermes 回答总是很短或者拒绝执行记忆指令。排查检查config/template.yaml中的system提示词。确保其中包含了关于记忆功能的明确指令。尝试提高temperature到 0.9让模型更“开放”。技巧在对话中你可以用更明确的指令引导它例如“请将‘我每周三下午开会’这个事实存入长期记忆。” 然后使用/audit检查是否成功。问题/audit 里看不到任何记忆或者记忆内容很奇怪。排查这通常是 LangMem 提取管道的问题。首先确认LANGMEM_MODEL_PROVIDER和LANGMEM_MODEL设置正确默认使用主聊天模型。其次模型可能不擅长执行你给的提取指令。你可以尝试在system提示词中强化记忆提取的格式要求。进阶调试直接查看src/services/memory/langmem_extractor.py的日志或者修改其代码打印出它发送给模型的原始提示词和返回结果这是定位问题最直接的方式。问题语义搜索召回的结果不相关。排查问题可能出在嵌入模型或检索策略上。首先确认你使用的OPENAI_EMBEDDING_MODEL适合你的文本类型短句、长文档。text-embedding-3-small是通用性较好的选择。调优尝试调整检索时的相似度阈值。在vector_store.py的检索函数中可以添加一个WHERE similarity 0.7之类的条件过滤掉低相似度的结果。也可以尝试调整ivfflat索引的lists参数在创建表时平衡检索速度和精度。6.3 性能优化与资源管理响应慢首次加载模型或检索大量记忆时会较慢。确保 Ollama 在利用 GPU如果可用。对于数据库确保pgvector索引已正确创建。可以考虑对记忆表进行分区或使用更快的索引类型如hnsw。内存/显存占用高Hermes-4-14B 的 Q8_0 版本在运行时需要约 10GB 的 RAM/VRAM。如果资源紧张可以尝试量化等级更高的版本如Q4_K_M但推理质量可能会略有下降。也可以调整 Ollama 的num_gpu和num_thread参数。OpenAI API 费用每次生成记忆嵌入都会调用 API。如果对话频繁会产生费用。监控方式是将OPENAI_EMBEDDING_MODEL暂时改为text-embedding-ada-002旧版更便宜进行测试或者考虑迁移到本地嵌入模型方案。6.4 进阶玩法与扩展思路这个项目是一个完美的起点你可以基于它进行各种实验更换核心模型Ollama 支持成百上千个模型。尝试拉取llama3.2、qwen2.5或command-r然后在.env和template.yaml中修改模型配置对比不同模型的推理风格和记忆配合效果。实现工具调用Hermes 模型原生支持函数调用Tool Use。你可以参考 Ollama 的文档在chat_session.py中集成一个简单的工具系统比如计算器、查天气、搜索文件让智能体真正“动手”做事。构建 Web 界面厌倦了 CLI用 FastAPI 或 Gradio 将核心的聊天和记忆接口包装成 HTTP API然后快速搭建一个简单的 Web 前端。这样你就可以在浏览器里和你的智能体对话了。连接真实数据源将记忆系统与你本地的笔记如 Obsidian、代码仓库或日历连接起来。让智能体不仅能记住你说的话还能记住你写过的文档和日程成为一个真正的个人知识中枢。实现记忆蒸馏与总结长期记忆库会越来越大。可以定期运行一个后台任务将相似或相关的记忆条目自动合并、总结成一条更精炼的“元记忆”避免信息冗余。这个项目的乐趣在于其“未完成”和“可塑性”。它没有给你一个完美的成品而是给了你一套功能完整、结构清晰的乐高积木。怎么搭能搭出什么完全取决于你的想象力和动手能力。我最享受的时刻不是它完美回答问题时而是当它出乎意料地以一种独特的方式组合了不同记忆给出一个让我拍案叫绝的回答或提问时——那感觉就像在观察一个真正思维的萌芽。