这几年团队里做 AI 原生应用的节奏很快但大家慢慢发现一个问题大部分人把大模型接进来以后做的还是“聊天机器人”或“文档问答机”。模型再聪明它也只能读、能说不能看、不能动。真正让大模型从“顾问”变成“员工”的是让它在理解之外具备感知和行动能力。我这次用开源项目 anythingLLM 搭了一套 AI Agent目标很直接——给大模型装上“眼睛”和“手”让它能自己查知识库、读网页、调接口、写文件最后把完整任务闭环跑下来。这篇文章就把我这几周从选型、配置到踩坑的完整过程记录下来给想自己做 Agent 又不想一上来就啃复杂框架的朋友一条能直接上手的路线。1. “眼睛”和“手”Agent 与聊天机器人的分水岭先把我理解的核心概念摆清楚。大模型本身是个“大脑”它擅长理解和生成语言但存在两个致命短板一是知识有截止日期不知道你私域里的最新信息二是它只会“说”不会“做”没法替你去查数据库、调 API、创建工单。Agent 做的事情就是在这颗大脑外面接上感官和四肢——用检索和文件解析充当“眼睛”用工具调用和接口操作充当“手”再用一套决策循环把两者串起来。我见过不少团队一开始就上 LangChain、AutoGen 这类重型框架结果被概念绕晕还没跑通第一个 Demo 就被各种抽象类劝退。这次我刻意选了 anythingLLM原因有三个第一它自带完整的 Web UI 和 API不用自己拼前端第二它支持本地模型和云端模型混用数据能留在我自己的机器上第三它的工作区Workspace天然做了知识库隔离多个业务场景可以同时跑而不互相污染。为了把概念说透我习惯用这个类比来解释你雇了一个应届毕业生当助理。如果只给他一张嘴他能跟你聊但什么都干不了如果你给他企业内网权限、给他一本产品手册、再给他一套工单系统账号他才能把“用户抱怨某个功能不好用”这句话转成“查询手册对应章节、定位问题原因、填写一条工单”。Agent 的本质就是这个助理的数字化版本anythingLLM 在这里充当的是“工位管理系统”——管权限、管知识、管工具清单。下面的对比表可以很直观地看到普通问答机器人和 Agent 的差异能力维度普通问答机器人带“眼睛”和“手”的 Agent知识来源模型预训练知识预训练知识 私域文档检索 实时 URL / API 拉取信息时效截止到训练时间可根据需要实时获取输出形式文字、代码文字 文件 数据库变更 外部系统操作结果决策链路直接回答理解意图 → 检索/观察 → 推理规划 → 执行动作 → 汇总反馈适用场景客服问答、知识查询工单处理、数据清洗、报表生成、自动化运维我这次选一个内部代号为“某项目”的售后场景来做验证用户的问题五花八门既涉及产品手册中的条款又要查实时的库存和物流状态最后还要能生成一张处理记录表。这个场景恰好把“眼睛”和“手”都覆盖了非常适合作为样例。2. anythingLLM 的 Agent 底座模型、工作区和工具的选型笔记2.1 我采用的部署拓扑anythingLLM 本身是个前后端一体的应用支持 Docker 部署也支持本地 Desktop 版。我这次用的是 Docker 版本因为要长期跑、要支持多个同事访问总不能一直开着桌面程序。整体拓扑不复杂anythingLLM 负责工作区管理、文档入库、向量检索和 Agent 调度本地大模型推理服务负责跑模型因为我有一部分数据不出内网的要求临时性的外部请求走系统自带的内置工具。向量库我直接用 anythingLLM 默认内置的存储方案没有额外接外部的向量数据库。原因很实在这个项目的知识库规模在几万段以内内置方案足够用省掉一套基础设施的运维成本。等到数据量更大、并发更高时再迁到独立向量库不迟。嵌入模型我也选择了本地跑的一个通用向量模型维度不高但处理中文技术文档够了。2.2 为什么开 Agent 模式而不是只用普通聊天anythingLLM 的新版本里提供了 Agent 功能开关默认情况下是普通聊天模式。如果你想让它具备“手”必须在工作区设置中把 Agent 模式打开同时配置对应的模型。这一步特别容易被忽略我一开始没开这个开关无论怎么提示工具就是不触发排了半天才意识到是功能没启用。打开之后anythingLLM 会把对话模式从“单轮问答”切换成“多轮决策循环”。模型不再直接吐答案而是先输出一个动作计划比如“我需要先检索知识库中的章节X再调用库存查询工具”然后逐项执行拿到结果后再继续推理。这个模式对模型本身有要求模型必须支持工具调用function calling 或类似机制否则决策循环跑不起来。2.3 模型选择的坑与判断标准模型选型是这个项目里最关键、也最容易翻车的环节。我的判断标准有三条第一必须支持 tool calling否则“手”无从谈起第二上下文窗口最好大于 8K因为 Agent 每执行一步动作都要把“历史对话 工具回执 检索片段”塞回上下文窗口小了容易截断关键信息第三中文指令遵循能力要过关否则提示词写再好模型也给你执行歪。我实测下来本地有几个开源模型在中文和工具调用之间平衡得不错而一些偏小的模型即使支持工具调用也会在复杂指令下漏参数、漏步骤。如果你只是做 PoC用云端大模型 API 会省很多事但如果知识库数据敏感、不能出内网那就得老老实实部署本地模型并且尽早把模型能力测试纳入选型流程。2.4 上下文窗口与文档切片的联动关系这个点容易踩坑我单独拎出来说。Agent 模式下系统提示词、知识库检索片段、工具返回内容、历史对话这四部分都要占上下文窗口。文档切片设太大一段检索结果就吃掉几千 token留给工具回执的余地就没了设太小语义完整性会受损检索召回质量下降。我在 AnythingLLM 里把文档切片的默认参数做了调整正文片段控制在 500 到 800 字左右重叠控制在 50 到 100 字既能保住段落的语义边界又不至于让单次检索返回的内容过多。这个参数要配合你选用的模型来调没有绝对最优值只能根据实测效果一点一点试。3. 给大模型装“眼睛”RAG、URL 读取和图片理解的真实落地“眼睛”这个词听起来玄乎落地无非三个层次知识库检索、实时信息拉取、视觉内容理解。这三个层次在 anythingLLM 里各有各的实现路径我逐个说。3.1 第一层知识库检索也就是 RAG先用“眼睛”读懂你塞给它的文档。anythingLLM 的工作区支持上传 PDF、Word、Markdown、TXT、CSV 等常见格式。上传后系统会自动做解析、切片、向量化用户提问时通过向量相似度召回相关片段喂给模型模型再基于这些片段作答。这是最经典的一层“眼睛”代码都不用写但参数和文档质量决定了效果。这里有一个容易被低估的点文档的原始结构会影响切片质量。我测试时发现如果直接丢进去一个排版混乱的 PDF解析出来经常是断行、乱序检索结果自然稀碎。后来我采用了一个笨但有效的做法先把 PDF 转成干净的 Markdown去掉页眉页脚和多余换行再喂给 anythingLLM。这步预处理虽然费点功夫但检索准确率提升非常明显。CSV 表格类数据也有讲究。anythingLLM 对 CSV 的解析默认按行切分如果你的表头信息很关键最好在文档里加一段“表结构说明”否则模型可能只看得到零星行列推断不出字段含义。我处理售后的库存表时就在文档开头写了一段字段说明比如“SKU_ID 表示商品编码QTY 表示可用库存”召回效果立刻好了很多。3.2 第二层实时信息拉取让眼睛“睁开”知识库里的信息是静态的顶多算“闭着眼睛记东西”。要让 Agent 能实时看到外界的当前状态就得用工具去拉取。anythingLLM 的 Agent 模式内置了网页读取工具可以让模型根据用户问题自行决定访问指定 URL 并提取正文。举个例子用户问“这个物流单号现在到哪了”Agent 的决策链路是这样的先判断这属于实时信息知识库查不到然后调用网页读取工具访问物流查询接口返回的页面或 JSON把拿到的结果解析后再结合产品手册中的配送政策组织成最终回答。整个过程里“眼睛”由知识库检索切换成了实时拉取模型自己决定该看哪里。实时拉取这里要非常注意超时和数据格式。我在内部接口调试时遇到过接口响应超过 30 秒的情况Agent 会一直挂着等结果给用户的感觉就是“卡死了”。后来我给自己接入的查询接口加了超时控制和重试机制超时直接返回“查询超时请稍后再试”不让模型空等。另外接口返回的 JSON 要做字段裁剪把无关日志、埋点字段去掉只留模型需要的核心字段这样可以省 token也能减少模型被噪音干扰的概率。3.3 第三层图片理解给“眼睛”加分辨率很多人忽略了文档里图片的信息量。产品手册中的截图、流程图、表格图片里面明明有答案但传统 RAG 只看文字提取结果图片内容全部丢失了。这一点我在测试时体会很深问一个关于“界面某个按钮在哪”的问题纯文字检索基本答不上来因为关键信息都在截图里。我的做法是利用多模态模型对文档里的关键图片做一轮“看图说话”生成一段对图片内容的文字描述然后把这段描述连同图片所在章节一起入库。相当于让大模型先替你把图“读”成文字再放进知识库让检索和推理继续使用。这样整体链路不需要额外改 anythingLLM 的代码只需要在文档预处理阶段加一步。如果你要处理的图片量很大可以考虑按需生成描述而不是全量生成。我在项目里只对产品手册中明确包含步骤截图的页面做处理既控制了成本又刚好补上了信息缺口。这一步做完之后关于“按钮位置”这类提问的准确率大幅提升用户体感从“答非所问”变成了“直接给出截图对应文字”。3.4 评估“眼睛”效果的小方法不要凭感觉判断视觉层好不好用要建立一套可复用的验证集。我准备了几十个典型问题分成三类纯知识库检索类、实时信息类、图片描述类。每次调整嵌入模型、切片参数或预处理流程后就用同一套问题跑一遍记录回答准确率和关键信息缺失率。这个方法帮我发现了几个隐蔽问题嵌入模型对专业缩写理解差、切片把表格拦腰截断、部分 PDF 的目录和正文被当成普通段落混切。如果你也想照做建议从一开始就维护这个问题集别等集成完才后悔。4. 给大模型装“手”工具调用、API 操作和动作回执的闭合光有眼睛看见了一切却什么也做不了那还是半个残废。“手”才是 Agent 从信息处理走向任务执行的关键。这一章是整个项目里最需要设计的一环我会从原理到实践拆开讲。4.1 工具调用的底层逻辑大模型的“手”本质是函数调用。模型在收到一个任务时不再直接输出最终答案而是先输出一个结构化的动作请求比如“我想调用 get_stock_info 这个函数参数是 SKU_IDxxx”。anythingLLM 拿到这个请求后替模型执行真实函数再把函数返回结果重新喂给模型模型看到结果后决定下一步动作或输出最终答案。我习惯把它类比成餐厅里的传菜流程主厨大模型不会自己跑出去买菜他会写下需求单“我需要三号冷库里的猪肉”传菜员Agent 框架去取回来主厨根据食材状态再决定怎么做菜。整个循环就是“提出需求 → 执行动作 → 反馈结果 → 继续决策”这也正是 Agent 的闭环逻辑。4.2 anythingLLM 自带工具的使用边界anythingLLM 的 Agent 模式默认带了一批基础工具比如网页读取、图片生成、音频生成等。对于做一个通用助手来说这些够用但到了实际的业务场景肯定不能满足于“生成一张图片”这种动作。我用的售后场景需要查询库存、写入工单、生成记录文件这些专业动作都得自己想办法接进去。我先明确了自己的边界需求不要为了炫技做一堆没什么实际价值的工具只把那些能显著增加自动化价值的动作真正接入。这样 Agent 的工具列表保持精简模型决策时也不容易被无关选项干扰。4.3 自定义工具的接入思路API 网关 标准接口anythingLLM 自身支持自定义技能/工具配置但不同版本的接入方式有差异。我采用了一个更通用、更稳妥的思路把一切自定义能力封装成标准 HTTP API挂在内部网关后面。anythingLLM 通过调用这个 API 来执行动作Agent 只相当于 API 的“翻译官”。具体来说我为项目封装了几个核心 API库存查询接口、工单创建接口、记录表生成接口。每个接口都遵循同样的规范入参用 JSON出参用 JSON包含 code、message、data 三个字段。这样设计有几个好处第一模型容易理解工具返回格式第二接口只要保证稳定返回Agent 就能稳定决策第三后续新增能力时只需新增接口不用改 Agent 本体逻辑。实际配置时我给每个工具写了一个清晰的描述信息说明“这个工具是干什么的、什么情况下用它、需要哪些参数”。这个描述非常关键因为大模型判断“现在该不该调用工具、该调哪个”完全依赖这段描述。描述写得模糊模型就会瞎猜。比如库存查询工具我的描述是“查询商品实时库存。当用户询问某个商品是否有货、库存数量、可售状态时使用。请输入商品 SKU_ID如未知则先通过知识库或追问获取。”4.4 动作回执如何闭环一次完整的“动手”过程“手”执行完动作还不算完回执闭环才是 Agent 区别于脚本的本质之处。工具返回的数据不能只存日志必须重新进入模型的推理上下文。我用库存查询场景演示一遍完整链路用户问“SKU_A003 有现货吗”Agent 第一步判断需要实时数据输出调用库存查询工具的动作请求anythingLLM 调用对应 API返回 JSON包含该 SKU 当前库存量和状态模型读取返回数据发现库存为 0但知识库中提到“缺货商品可预约到货通知”于是自动追加回答“当前无现货可预约到货通知预计补货周期为 3 至 5 天”。这个链路里工具回执就是“手”的信息反馈“看到结果后决定怎么做”是模型的推理能力。二者缺一不可。如果工具返回的数据结构复杂或不稳定模型很容易在决策环节出错。我建议把工具返回内容尽量精简、语义化最好让一个没有技术背景的运营也能看懂这个 JSON 在说什么。4.5 “手”的安全边界给大模型装上“手”之后最让人担心的就是乱动、误操作。尤其当工具涉及数据写入、状态变更时必须建立安全边界。我在项目里做了四层防护第一工具权限最小化Agent 能调的接口只能做它业务范围内的事不做全量数据库读写映射。第二危险操作强制确认所有写操作创建工单、修改状态在动作执行前都要经过二次确认或配置白名单范围内才自动执行。第三超时和重试限制每个工具调用都有超时阈值超时即终止避免 Agent 在某一步上无限循环。第四完整的巡检日志anythingLLM 会保存对话和动作轨迹我在此基础上把工具调用参数和返回结果也做了留痕一旦出现误操作可以快速定位。有了这层护栏我才敢把 Agent 对外开放给团队成员试用。技术上说“能做”和“允许做”是两码事护栏不是阻碍而是让自动化可持续运行的保险丝。5. 眼手协同提示词设计和决策链路的调试手记眼睛和手都装好了真正让 Agent 变得好用的是大脑里那套“怎么想、怎么判断”的提示词和决策链路。这一章是我花时间最多、也是收益最明显的部分。5.1 系统提示词的框架anythingLLM 的每个工作区都支持自定义系统提示词System Prompt。这个提示词就是 Agent 的“岗位说明书”和“行为准则”。我给售后 Agent 设计的系统提示词包含四个部分角色定义、能力边界、工作流程、回答风格。角色定义让模型明确“你是谁、服务对象是谁、业务范围是什么”能力边界告诉模型“哪些问题能直接回答哪些必须查证后回答哪些不能回答”工作流程是最关键的我强制规定了一个决策顺序“当用户问题时第一优先检索知识库涉及实时状态时必须调用对应查询工具只有拿到充分信息后才组织最终回答”回答风格则规定了口语化、简洁、带引用来源。这套提示词模板在实际运行中效果不错因为 Agent 不像常规 ChatGPT 那样自由发挥而是像遵循 SOP 的员工那样按流程办事。如果你也想照搬我建议把工作流程部分写得极细致甚至用编号列表模型对这种结构化指令的遵循度会明显提高。5.2 最常见的决策错误没有检索就乱答调试过程中我遇到最多的错误模型行为是“编答案”。用户问一个产品政策问题模型不检索知识库直接凭预训练记忆作答结果就是张冠李戴。针对这个问题我在系统提示词里加了一条“硬性规则”只要问题涉及知识库文档中可能存在的内部信息必须先执行知识检索禁止跳过该步骤直接作答并引用知识库的段落编号作为依据。这里的关键是让模型形成“先看后说”的习惯而不是先想后说。另外我在排障时发现模型的温度参数设置过高会导致决策不稳定——同样的提问这次会引用知识库下次就直接回答了。我把 temperature 调低到 0.1 至 0.3 区间配合规则提示词跑偏率明显下降。这两个调整组合起来效果比单纯换一个大模型还明显。5.3 用 Agent 事件轨迹来调试anythingLLM 在 Agent 模式下会记录每一步的执行轨迹包括模型的动作请求、工具调用参数、工具返回结果。调试时就盯着这个轨迹看基本能还原模型每次决策的“心路历程”。有一次 Agent 在应该调用库存工具时却调用了网页读取工具我一开始以为是提示词不够好后来查日志发现是工具描述里“库存”两个字没有出现模型没能把用户问题里的“有货吗”关联到库存查询工具。修改工具描述加上“有货、现货、库存数量”这些触发词后决策准确率大大提升。这件事给我的启发是调试 Agent 不是玄学要利用好执行轨迹把每个错误关联到具体环节再针对性调整提示词或工具描述。5.4 防止 Agent 陷入“过度工具化”还有一种常见毛病是模型过度依赖工具。哪怕是问一个常识性问题模型也想走一遍检索导致响应时间从 2 秒变成 20 秒。我在系统提示词里专门加了一条“当问题属于常识性或已在对话历史中明确出现过时可以直接作答无需调用工具。”同时在工具描述里强化“何时使用、何时不用”的说明。经过测试集评估无效工具调用次数下降了约六成整体响应体验改善明显。这里的教训是工具是给模型兜底的不是让它显摆的。一个优秀的 Agent 应该知道什么时候该省力什么时候该较真。6. 端到端实战一个能查文档、能问数据、能写记录的售后 Agent 案例最后用一个完整案例把前面所有内容串起来方便你照着一路搭建、验证。6.1 场景定义与前置条件场景是这样的售后团队每天收到大量重复提问涉及产品手册、库存状态、赔付流程。我的目标是做一个 Agent既能回答手册问题又能查实时库存还能把每个处理结果写入一张记录表取代原来“人工查手册 人工登录后台 手动填表”的流程。前置条件需要三样东西一台能跑 anythingLLM 和本地模型的机器一份干净的产品手册文档Markdown 格式一套已经封装好的查询和写入 API。如果你没有现成的 API可以先拿一个 mock 接口做验证关键是流程跑通。6.2 搭建步骤整个搭建过程分五步走。第一步部署 anythingLLM 并创建独立工作区命名为“售后助手”。第二步在设置里打开 Agent 模式配置支持工具调用的模型和嵌入模型。第三步把产品手册上传到工作区在预览界面确认切片清晰、无乱码。第四步配置工具把库存查询 API 和工单创建 API 按标准格式填入工具配置写好描述信息。第五步编写系统提示词包含角色定义、硬性检索规则、工具选用规则、回答格式要求。这五步做完基础 Agent 已经能跑了。我第一次启动测试时模型差点在“是否调用工具”这一步卡住后来发现还是工具描述的问题。把触发词写明确之后立刻通畅了。6.3 验证效果与数据观察我用提前整理好的测试集跑了一轮覆盖三类问题产品手册类“保修期是多久”、库存类“A003 有货吗”、复合类“A003 没货的话我应该怎么处理”。观察 Agent 的决策轨迹后发现产品手册类问题Agent 会先执行知识检索返回手册里的条款原文回答质量高且自带来源库存类问题Agent 会跳过检索直接调用库存 API但有时需要追问一次 SKU_ID复合类问题Agent 能先后做两轮动作先查库存再查手册最终把赔付流程和缺货状态融合回答。我特别关注了“写记录”这一步也就是调用写入 API 的真实操作。首次验证时 API 返回了成功但打开数据库一看数据字段错位了原因是模型在调用时把两个参数的位置搞反了而工具的 JSON Schema 里没有做参数类型校验。后来我在 API 层补了字段校验和必填判断错误立即被拦截模型拿到的回执变成了“参数缺失请检查 SKU_ID”它就会重新组织请求。这件事再次证明工具层要有防御性设计不能默认模型传参永远正确。6.4 我的经验总结与后续扩展整个项目从选型到验证前后花了大概两周最大的体会是工具调用的质量取决于四件事——模型基础能力、工具描述准确性、提示词规则强度、回执数据规范性。这四件事环环相扣任何一个短板都会让 Agent 的整体能力大打折扣。如果你想在这个基础上继续扩展我建议优先考虑两条线一是加上语音入口让用户直接说话提问Agent 自动把语音转文字后走同样的决策链路二是针对工具做更细粒度的权限体系不同角色看到的工具列表不同实现更可控的自动化授权。我自己下一步准备做的是把日常售后问题按周汇总利用 Agent 自动生成一份高频问题报告把“被动问答”变成“主动洞察”那是挺有意思的方向。最后说一个我在实际操作中反复触碰到的点别一上来追求“全自动、零人工”。最稳妥的节奏是先把“人看结果再执行”跑顺再逐步放开自动执行的范围。Agent 的能力边界是在一次次信任建立中慢慢扩大的。