免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

【程序员必看+收藏】构建可靠AI Agent应用:提示词工程、工作流与RAG实战指南(TaoToken统一Key接入篇)

【程序员必看+收藏】构建可靠AI Agent应用:提示词工程、工作流与RAG实战指南(TaoToken统一Key接入篇) 1. 从原型到生产AI Agent 应用为什么总在“最后一公里”翻车AI Agent 这个词现在几乎成了所有技术团队的标配话题。你随便打开一个技术社区满屏都是“我用 Agent 做了个自动写周报的工具”“我用 Agent 实现了客服自动化”。但真正把 Agent 推到生产环境、稳定跑上三个月的人心里都清楚原型 Demo 和可靠落地之间隔着一整条工程化的鸿沟。我见过太多团队卡在同一个地方。Demo 阶段用自然语言写一段提示词接上模型 API跑通一个问答链路大家觉得“成了”。可一旦要接入真实业务、要处理边界情况、要保证输出格式稳定、要让非技术同事也能维护问题就全冒出来了。提示词越改越乱工作流全靠口口相传知识库检索出来的内容驴唇不对马嘴模型偶尔还会被用户一句话带偏输出一堆莫名其妙的东西。这些问题的根源其实不在于模型不够强而在于我们把 Agent 当成了一个“聊天机器人”来对待而不是一个需要工程化设计的软件系统。一个可靠的 AI Agent 应用至少需要三条主线同时支撑提示词工程负责定义 Agent 的行为边界和输出规范工作流编排负责把复杂任务拆解成可执行、可观测的步骤RAG 检索增强负责让 Agent 能够访问和利用私有知识。这三条线缺一不可而且必须用工程化的方式来管理而不是靠“感觉”去调。这篇文章面向的是已经写过几个 Agent Demo、但想把它们真正推到生产环境的开发者。我会围绕提示词工程、工作流 DSL、RAG 检索链路这三条主线给出可复制的配置模板和验证步骤并且演示如何通过 TaoToken 的统一 Key 和 API 通道接入模型服务让你能快速验证端到端可用性。整篇内容偏实操代码和配置都可以直接拿去改。2. TaoToken 统一 Key 接入为 Agent 应用准备模型通道在开始写提示词和工作流之前得先把模型通道准备好。很多开发者在 Agent 开发初期会同时对接好几个模型服务商每个服务商的 API Key 格式不一样、Base URL 不一样、计费方式也不一样光是管理这些凭证就够头疼的。更麻烦的是当你想在 Agent 里做模型切换或者 A/B 测试时代码里到处散落着不同的 SDK 调用改起来非常痛苦。TaoToken 在这里扮演的角色就是提供一个统一的模型接入层。你可以把它理解成一个“模型网关”你只需要维护一套 API Key通过统一的 Base URL 去调用不同厂商的模型Agent 代码里不需要关心底层到底是哪家模型在提供服务。这对于需要频繁切换模型、或者想让 Agent 在不同任务上使用不同模型的场景来说能省掉大量胶水代码。2.1 获取 API Key 与配置 Base URL首先你需要有一个 TaoToken 的账号。访问官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 完成注册后进入控制台创建 API Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 在 API Keys 页面点击创建把生成的 Key 复制下来保存好。接下来是 Base URL。TaoToken 的 API 入口是 https://taotoken.net/api 注意这个地址后面不要加 UTM 参数直接作为 OpenAI 兼容接口的 base_url 使用即可。如果你用的是 OpenAI SDK 或者任何兼容 OpenAI 接口的客户端把 base_url 指向这个地址api_key 填你刚才创建的 Key就可以开始调用了。这里有一个细节需要注意很多 Agent 框架比如 LangChain、LlamaIndex、AutoGen默认会去读环境变量OPENAI_API_KEY和OPENAI_BASE_URL。你可以直接在 shell 里 export也可以写在.env文件里。我习惯用.env管理因为不同项目之间可以隔离。# .env 文件示例 OPENAI_API_KEYsk-你的TaoToken密钥 OPENAI_BASE_URLhttps://taotoken.net/api如果你用的是 Python可以这样加载from dotenv import load_dotenv import os from openai import OpenAI load_dotenv() client OpenAI( api_keyos.getenv(OPENAI_API_KEY), base_urlos.getenv(OPENAI_BASE_URL) ) response client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: 用一句话解释什么是 RAG}] ) print(response.choices[0].message.content)这段代码跑通说明你的模型通道已经就绪。后面所有的提示词实验、工作流验证、RAG 检索测试都会复用这个 client。2.2 模型 ID 的填写与选择TaoToken 支持多种模型你在调用时需要指定正确的 model ID。常见的比如gpt-4o、gpt-4o-mini、claude-3-5-sonnet等。具体支持哪些模型可以在控制台的模型列表页面查看或者参考接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。这里有一个容易踩的坑不同模型对参数的支持程度不一样。比如有些模型不支持temperature参数有些模型对max_tokens的上限要求不同。如果你在 Agent 里硬编码了某个参数切换到另一个模型时可能会报错。我的建议是在 Agent 配置层做一层参数适配把模型相关的参数抽出来而不是散落在业务代码里。另外如果你打算长期做 Agent 开发可以考虑使用 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 它在频繁调用场景下会更划算。不过这是后话先把基础通道跑通再说。3. 提示词工程实战用结构化模板替代“感觉调参”提示词工程这个词被说得有点玄乎好像是一门玄学。但在我看来它本质上就是给 AI 写“需求文档”。你给一个新人交代任务时如果只说“帮我处理一下这个数据”他大概率会做错但如果你说清楚角色、背景、输入输出格式、边界条件他就能做得八九不离十。提示词也是一样的道理。3.1 系统提示词的结构化模板一个可靠的系统提示词至少应该包含四个部分身份Role、上下文Context、示例Examples、输出规范Output Format。我把它整理成一个可以直接复制的模板# Role: 数据提取流水线 ## Profile - language: 中文 - description: 你是一个严格按规则执行的数据提取组件不是人类助手 - background: 你运行在自动化数据处理管道中输入是原始文本输出是结构化 JSON - personality: 无情感、无解释、无寒暄 - expertise: 文本解析、实体识别、JSON 格式化 - target_audience: 下游数据处理程序 ## Rules 1. 基本原则 - 只输出 JSON不输出任何其他文字 - 不解释、不道歉、不确认 2. 行为准则 - 如果字段无法从原文提取值设为 null - 日期统一格式化为 YYYY-MM-DD 3. 限制条件 - 禁止输出 markdown 代码块标记 - 禁止在 JSON 前后添加任何说明文字 ## Workflows - 目标: 从输入文本中提取指定字段并返回 JSON - 步骤 1: 读取输入文本识别所有目标字段 - 步骤 2: 对每个字段进行格式校验和标准化 - 步骤 3: 组装 JSON 并输出 - 预期结果: 一个合法的 JSON 对象可直接被 json.loads() 解析 ## Output Format { name: string | null, date: YYYY-MM-DD | null, amount: number | null, category: string | null } ## Initialization 作为数据提取流水线你必须遵守上述 Rules按照 Workflows 执行任务。这个模板的关键在于角色定位远离“人类助手”减少模型输出废话的概率规则里反复强调“只输出 JSON”输出格式给出明确的 schema。实测下来这种结构化提示词比“请你帮我提取一下这些信息”的模糊指令输出稳定性高出一个数量级。3.2 少样本示例的正确用法少样本示例Few-shot Learning是提升 Agent 输出质量最有效的手段之一尤其是当你需要模型按照特定格式输出时。但很多人用错了方式把示例随便堆在提示词里结果模型反而被带偏。设置示例时有几个原则需要遵守。第一示例质量要高不要放模棱两可的例子。第二正确和错误的示例要标注清楚不要把对的标成错的。第三示例要乱序不要把正确示例全放一起、错误示例全放一起。第四正确和错误示例的数量要均衡。第五示例之间要有细微差别但输出结果不同这样才能让模型学会区分边界。举个例子如果你要训练 Agent 识别“有效提问”和“无效提问”可以这样写## Examples 输入: 帮我查一下北京明天的天气 输出: {valid: true, reason: 明确的查询意图} 输入: 你好 输出: {valid: false, reason: 无明确查询意图} 输入: 北京明天天气怎么样 输出: {valid: true, reason: 明确的查询意图} 输入: 今天心情不好 输出: {valid: false, reason: 无明确查询意图}注意这里正确和错误示例是交替出现的而且每组的差别很小但输出结果完全不同。这种设计能让模型更准确地学到判断边界。3.3 输出格式约束与工程兜底即使你在提示词里写了“只输出 JSON”模型仍然有可能输出 markdown 代码块、或者在前面加一句“好的以下是提取结果”。这是模型的“解释惯性”在作祟。要解决这个问题需要提示词约束和工程兜底双管齐下。提示词层面可以在开头和结尾反复强调输出要求并且加入 badcase 示例# CRITICAL: OUTPUT JSON ONLY # ANY OTHER TEXT WILL CAUSE SYSTEM FAILURE **FORBIDDEN**: - NO explanations - NO I will process... - NO markdown code blocks - NO text before { or after } # FINAL REMINDER Your ENTIRE response must be valid JSON. Start with { and end with }.工程层面拿到模型输出后不要直接json.loads()而是先做一层清洗截取第一个{和最后一个}之间的内容再去解析。这样即使模型多输出了一两句废话也能被兜住。import json import re def safe_parse_json(text: str): # 截取第一个 { 和最后一个 } 之间的内容 start text.find({) end text.rfind(}) if start -1 or end -1: raise ValueError(未找到 JSON 内容) json_str text[start:end1] return json.loads(json_str)这个函数看起来简单但在生产环境里能挡掉大量因为模型输出不规范导致的解析错误。4. 工作流 DSL用结构化语法描述 Agent 执行路径当 Agent 的任务从“单轮问答”变成“多步骤执行”时自然语言描述的工作流就开始力不从心了。你写一段“先做 A然后根据 A 的结果决定做 B 还是 C最后汇总输出”模型可能理解得七七八八但一旦流程复杂起来歧义就会指数级放大。这时候就需要 DSLDomain-Specific Language领域特定语言。DSL 通过结构化语法能比自然语言更准确地描述业务流程。对于 Agent 工作流来说Mermaid 是一个非常好的选择它语法简单、与 Markdown 集成度高而且模型本身对 Mermaid 的理解也相当不错。4.1 用 Mermaid 描述工作流假设你要构建一个“客服工单自动分类与回复”的 Agent工作流大致是接收用户消息 → 判断意图 → 如果是咨询类检索知识库并生成回复如果是投诉类转人工并生成工单摘要如果是其他返回引导话术。用 Mermaid 可以这样描述flowchart TD A[接收用户消息] -- B{意图识别} B --|咨询| C[检索知识库] C -- D[生成回复] D -- E[返回用户] B --|投诉| F[生成工单摘要] F -- G[转人工] B --|其他| H[返回引导话术] H -- E这段 DSL 比自然语言描述清晰得多而且可以直接嵌入到系统提示词里让模型按照这个流程来执行。你甚至可以让模型在每一步输出当前所处的节点方便调试和观测。4.2 工作流 DSL 的配置模板在实际工程中我习惯把工作流定义成一个独立的配置文件而不是硬编码在提示词里。这样修改流程时不需要动提示词降低耦合。下面是一个 YAML 格式的工作流配置示例workflow: name: customer_service_agent version: 1.0 steps: - id: receive_message type: input description: 接收用户消息 - id: intent_classify type: llm_call model: gpt-4o-mini prompt_template: | 判断以下用户消息的意图只返回 JSON {intent: consult | complaint | other} 用户消息{{message}} output_key: intent_result - id: route_by_intent type: switch condition: {{intent_result.intent}} cases: consult: - id: retrieve_knowledge type: rag_retrieve query: {{message}} top_k: 3 output_key: knowledge_chunks - id: generate_reply type: llm_call model: gpt-4o prompt_template: | 基于以下知识库内容回答用户问题 {{knowledge_chunks}} 用户问题{{message}} output_key: reply complaint: - id: generate_ticket type: llm_call model: gpt-4o-mini prompt_template: | 为用户投诉生成工单摘要包含问题描述和紧急程度 {{message}} output_key: ticket_summary other: - id: fallback_reply type: static value: 抱歉我暂时无法处理您的请求请稍后再试。 - id: return_output type: output value: {{reply}}这个配置把工作流的每个步骤、每个分支、每个步骤的输入输出都定义清楚了。你可以写一个简单的执行引擎来解析这个 YAML也可以把它转换成 LangGraph 或 AutoGen 的图结构。关键是流程本身变成了可版本管理、可 diff、可测试的配置文件而不是散落在提示词里的自然语言。4.3 让 Agent 输出思维链Mermaid 还有一个很实用的场景让 Agent 在回答之前先用 Mermaid 输出自己的思维流程。这就是 CoTChain-of-thought的一种实现方式。通过查看流程图你可以快速定位到 Agent 理解不到位的地方。比如你可以这样提问我的问题是{{user_question}} 请先重新梳理我的问题使问题更加清晰明确。如果问题有多个细节和要求全部梳理出来使用 Mermaid 流程图列出问题的所有细节和你的解答思路然后再回答问题。Agent 会先输出一个 Mermaid 流程图展示它对你问题的理解。如果流程图里某个节点理解错了你一眼就能看出来然后针对性地修改提示词。这比等它输出一大段错误答案再去排查效率高得多。5. RAG 检索链路验证与常见报错排查RAG 是 Agent 应用里最容易出问题的环节。检索不到、检索不准、检索到了但模型不用这三个问题几乎每个做 RAG 的人都会遇到。这一节我会给出一个完整的 RAG 检索链路验证步骤以及几个常见报错的排查方法。5.1 最小可验证 RAG 链路先搭建一个最小可用的 RAG 链路确认端到端能跑通再逐步优化。下面是一个用 Python 实现的简化版 RAG 流程import numpy as np from openai import OpenAI import os from dotenv import load_dotenv load_dotenv() client OpenAI( api_keyos.getenv(OPENAI_API_KEY), base_urlos.getenv(OPENAI_BASE_URL) ) def get_embedding(text: str) - list: response client.embeddings.create( modeltext-embedding-3-small, inputtext ) return response.data[0].embedding def cosine_similarity(a, b): a, b np.array(a), np.array(b) return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) # 模拟知识库 knowledge_base [ TaoToken 的 API 入口是 https://taotoken.net/api兼容 OpenAI 接口。, 创建 API Key 需要进入控制台的 API Keys 页面。, Coding Plan 适合长期高频调用的编码场景。, ] # 预计算知识库向量 kb_vectors [get_embedding(doc) for doc in knowledge_base] def retrieve(query: str, top_k: int 2): query_vec get_embedding(query) scores [cosine_similarity(query_vec, vec) for vec in kb_vectors] ranked sorted(enumerate(scores), keylambda x: x[1], reverseTrue) return [knowledge_base[i] for i, _ in ranked[:top_k]] # 验证检索 query TaoToken 的 API 地址是什么 results retrieve(query) for r in results: print(r)跑通这段代码你会看到检索出来的内容确实和问题相关。这说明你的 Embedding 模型和检索逻辑是通的。5.2 常见报错与排查报错一401 Unauthorized这是最常见的错误通常是因为 API Key 没有正确设置。检查你的.env文件里OPENAI_API_KEY是否填写正确以及代码里是否正确加载了环境变量。如果你用的是 TaoToken 的 Key确认它没有过期并且有足够的额度。报错二local proxy failed / connection error这个报错通常和网络环境有关。检查你的 Base URL 是否填写正确应该是https://taotoken.net/api不要多加斜杠或者路径。如果你在公司内网确认防火墙没有拦截对外的 HTTPS 请求。报错三reading choices 时返回空有时候模型返回的choices数组是空的或者message.content是None。这通常是因为模型触发了内容安全策略或者请求参数有问题。检查你的max_tokens是否设置得太小以及提示词里是否有敏感内容。另外如果你用的是流式输出记得正确处理delta而不是message。报错四OAuth 相关错误如果你在使用某些需要 OAuth 认证的客户端比如 Claude Code 的某些配置可能会遇到 OAuth 报错。这时候需要检查你的认证配置是否正确。如果你是通过 TaoToken 接入确保你使用的是 API Key 认证而不是 OAuth 流程。具体的接入方式可以参考文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。5.3 RAG 检索质量优化检索跑通之后下一步是优化质量。有三个方向可以入手第一切分策略。不要按固定字符数切分文档要按语义切分。比如按段落、按标题层级、按句子边界。如果文档结构复杂可以用 Agent 辅助切分。第二重排Re-rank。向量相似度检索出来的 Top-K 结果不一定是最相关的。可以加一个重排模型对检索结果进行二次排序。TaoToken 支持多种模型你可以用一个小模型来做重排。第三提示词引导。在生成回复的提示词里明确要求模型“必须基于检索到的内容回答如果检索内容不包含答案就说不知道”。这能有效减少模型编造答案的情况。6. 持续迭代从能跑到好用把 Agent 从原型推到生产不是一次性的工作而是一个持续迭代的过程。提示词需要根据 badcase 不断修补工作流需要根据业务变化不断调整RAG 知识库需要定期更新。这里分享几个我在实践中总结的经验。第一建立 badcase 记录机制。每次 Agent 输出不符合预期时把输入、输出、期望输出记录下来。这些 badcase 是你优化提示词和工作流的最宝贵素材。你可以把它们整理成 few-shot 示例直接加到提示词里。第二用指标驱动优化。不要凭感觉说“好像好了一点”要定义明确的指标。比如意图识别的准确率、JSON 解析的成功率、检索命中率、用户满意度。有了指标你才能知道每次修改到底有没有效果。第三快速验证小步迭代。AI 项目的构建本身就是不断迭代的过程训练和错误分析的成本并不高。当你有一个场景可能可以用 Agent 解决时立刻动手做一个最小验证跑通了再逐步完善。不要一开始就追求完美架构那样只会拖慢进度。如果你在接入过程中遇到问题可以先去 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 检查 Key 状态或者查阅接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。想快速验证模型效果的话模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 可以直接测试。长期做编码和 Agent 开发的话Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 会更适合。最后说一个我踩过的坑不要试图用一个“万能 Agent”解决所有问题。我一开始把所有功能都塞进一个 Agent 里提示词越写越长工作流越来越复杂最后连自己都维护不动了。后来拆成多个专职 Agent每个 Agent 只负责一个明确的任务通过工作流编排串联起来反而稳定得多。Agent 的边界越清晰行为就越可控。
返回列表