Go AI Agent 实战 07|模型幻觉、能力边界与成本控制

本系列共 10 阶段 ,面向有 Go 后端基础的开发者,全程用 Go 手写实现。

当前进度:阶段一 大模型基础 · 第 7 课

上一篇:JSON 结构化输出与 Go 后端校验

这一课完成后,第一阶段「AI 与大语言模型基础」就正式结束了。

前面我们已经学过 LLM 的基本原理、Token、上下文窗口、Prompt、Temperature 和 JSON 结构化输出。现在需要把这些知识整合起来,回答三个工程问题:

  1. 为什么模型有时会一本正经地说错话?
  2. 哪些事情适合交给模型,哪些必须由 Go 后端负责?
  3. 如何控制真实项目中的模型调用成本?

这些问题会直接影响后续 AI 应用的可靠性、架构和开发成本。

一、本课学习目标

  • 理解模型幻觉的常见原因与应对措施。
  • 区分模型生成能力和传统后端的确定性逻辑。
  • 理解模型 API 的输入、输出成本,以及 Agent 多轮调用带来的额外开销。
  • 设计一套基本的 Go AI 服务可靠性控制方案。
  • 完成第一阶段的知识整合,为真实 API 调用做好准备。

二、模型为什么会产生幻觉?

所谓模型幻觉(Hallucination),是指模型生成了看似合理、实际却不准确或缺乏依据的内容。

例如,你问:

Go 某个最新版本中的某个函数应该怎么调用?

模型可能生成一个看起来非常专业的函数名、参数列表和代码示例,但这个 API 实际上根本不存在。

为什么会发生这种情况?

1. 模型的核心任务是生成内容,不是自动核实事实

大语言模型根据输入上下文和学到的模式生成后续 Token。它并不会因为某句话写得流畅,就自动确认这句话一定是真的。

可以把它理解为:

  • 模型负责根据上下文生成一个可能合适的回答。
  • 检索系统负责查找外部资料。
  • Go 后端负责执行程序规则和校验。
  • 测试与业务验证负责发现实际错误。

这也是为什么模型能够写出语法看似合理、但无法编译的代码。

2. 常见的幻觉原因

原因 例子
训练知识不完整 不知道某个新版本库的 API
信息已经过时 根据旧版本文档回答新版本问题
用户提供的信息不足 缺少报错日志,却直接推断出唯一原因
上下文太长或关键信息缺失 忽略前面提到的版本约束
生成机制的局限 生成了合理但不真实的函数名或事实

这里需要注意:并非所有错误都属于严格意义上的幻觉。有些错误源于信息不足、上下文管理不当或工具调用失败。但对应用工程而言,它们都需要被妥善处理。

三、Go 后端如何降低幻觉风险?

我们用一个技术助手的例子说明。用户问:

请告诉我 Eino 最新版本中,某个组件的初始化函数怎么写。

如果直接让模型回答,它可能依赖已有知识生成代码。更可靠的系统可以增加资料检索和验证环节:

text 复制代码
用户提出技术问题
      ↓
Go 后端识别问题与约束 ------ 库版本、问题类型、权限与预算
      ↓
检索可信资料 ------ 官方文档、项目源码、指定版本说明
      ↓
模型根据问题和资料生成答案
      ↓
Go 后端验证与返回 ------ 结构校验、必要的代码测试、来源信息

这套流程不意味着回答一定正确,但它比单纯依赖模型的已有知识更容易验证。

实际开发中,可以采用以下策略:

  1. 给出明确上下文:例如 Go 版本、库版本、错误日志和目标。
  2. 检索可信资料:优先使用官方文档、源码和经过审核的知识库。
  3. 要求引用来源:让用户能够检查关键结论依据;但要注意,模型生成的引用本身也可能是假的,必须核实。
  4. 执行程序验证:对 Go 代码进行编译、测试或静态检查。
  5. 允许模型表达不确定性:资料不足时,应允许它说明无法确定,而不是强迫它给出答案。
  6. 设置后端约束:对权限、资金、库存、数据库写入等关键操作,必须由程序执行确定性检查。

一个重要的工程原则

不要让模型成为唯一的事实来源,更不要让模型成为唯一的安全边界。

例如,在你熟悉的电商项目中,库存是否充足应由数据库或可靠的库存服务判断,而不是让模型根据对话内容决定库存数量。

模型可以解释库存规则、生成操作建议,甚至提出工具调用请求,但实际扣库存仍需要由 Go 后端完成校验和原子操作。

四、模型的能力边界:什么该交给 LLM?

这是设计 AI 应用时最重要的架构判断之一。

你已经熟悉传统 Go 后端。可以把 LLM 看作一个新增的能力组件,而不是整个系统的替代品。

任务 更适合谁负责? 原因
理解用户的自然语言问题 LLM 擅长语言理解与表达
将问题分类为 Go、Redis 或 MySQL LLM 或规则系统 模型灵活,规则更确定
校验请求参数是否为空 Go 后端 规则明确、结果确定
判断用户是否有权限删除文章 Go 后端 必须执行可信的权限校验
查询数据库中的真实文章 Go 后端或受控工具 需要访问真实数据
总结检索到的文章 LLM 擅长归纳和自然语言生成
原子扣减库存 数据库或库存服务 需要事务或原子操作保证一致性
根据文档回答技术问题 LLM + 检索 模型负责组织答案,资料提供依据
决定是否执行高风险操作 Go 后端权限策略 + 必要的人工确认 不能只相信模型的判断

记住这条分工原则:

  • LLM:处理模糊的语言任务。
  • Go 后端:执行确定的业务规则。
  • 数据库与基础设施:保存事实并保障一致性。
  • 检索、测试与监控:为模型输出提供证据和验证。

这也解释了为什么 AI 应用开发仍然需要扎实的后端工程能力。接入大模型不会让 Gin、MySQL、Redis、Context、错误处理和权限控制变得不重要,反而会增加新的边界需要管理。

五、模型调用成本:钱究竟花在哪里?

真实模型 API 通常会根据输入 Token、输出 Token、模型档位以及具体服务的计费规则收费。

常见的两个指标是:

  • 输入 Token:System Prompt、用户消息、历史对话、检索资料以及其他随请求发送的内容。
  • 输出 Token:模型生成的回答,以及某些服务计费口径中包含的其他输出内容。

注意:缓存 Token、推理 Token、工具调用等是否单独计费,取决于具体服务。后续接入 API 时必须查阅对应的官方价格说明。

1. 计算单次调用成本

假设某模型的价格为:

  • 输入:每 100 万 Token 收费 1 美元。
  • 输出:每 100 万 Token 收费 4 美元。

假设一次请求:

  • 输入 5,000 Token。
  • 输出 1,000 Token。

那么:

text 复制代码
输入成本 = 5,000 ÷ 1,000,000 × 1 = 0.005 美元
输出成本 = 1,000 ÷ 1,000,000 × 4 = 0.004 美元
总成本   = 0.005 + 0.004 = 0.009 美元

也就是一次调用约 0.009 美元。

这些价格是用于练习的假设值,并非任何模型当前的真实报价。

2. 估算调用量增长后的成本

以同样的价格,把调用次数放大到 1,000 次:

参数 取值
调用次数 1,000
每次输入 Token 5,000
每次输出 Token 1,000
输入价格 $1 / 100 万 Token
输出价格 $4 / 100 万 Token
输入总量 5,000,000 Token
输出总量 1,000,000 Token
估算总成本 约 9.00 美元

这个估算没有考虑缓存折扣、额外计费项目、重试和其他服务费用,属于基础估算,而不是账单预测。

3. 为什么 Agent 可能比普通聊天贵?

普通问答可能只调用模型一次,而 Agent 为完成任务可能调用多次。

例如,用户提出:

帮我查一下项目中 Redis 连接失败的原因,分析日志并给出修改方案。

一个 Agent 可能执行以下步骤:

  1. 模型分析任务。
  2. 模型请求调用日志查询工具。
  3. Go 后端执行工具并返回日志。
  4. 模型分析日志。
  5. 模型请求读取配置文件。
  6. Go 后端返回经过授权的配置内容。
  7. 模型综合结果并生成最终回答。

这里的工具执行本身未必产生模型 Token 费用,但模型每次调用的输入和输出可能都会产生费用。后续请求也可能重复携带部分历史上下文。

所以,Agent 成本不仅取决于最终回答的长度,还取决于中间调用次数和每次请求携带的数据量。

六、如何在 Go 后端控制成本和风险?

结合你熟悉的 Go 服务架构,建议从以下几个方向入手。

1. 限制请求时间

使用 context.WithTimeout 为模型请求设置时间上限,避免请求长时间占用资源。

go 复制代码
ctx, cancel := context.WithTimeout(
	context.Background(),
	30*time.Second,
)
defer cancel()

这段代码只是创建了一个带超时的 Context。要真正限制 HTTP 请求,还必须把这个 ctx 传给支持 Context 的 HTTP 请求或模型客户端。如果模型客户端不使用它,超时取消就不会自动生效。

2. 限制输出长度

根据业务设置合理的最大输出 Token 数。

例如,分类接口只需要少量字段,就不应该允许模型生成一篇几千字的解释。

3. 控制重试次数

遇到网络临时故障时,可以进行有限重试,但需要:

  • 设置最大重试次数。
  • 设置总耗时上限。
  • 对限流错误采用合理的退避策略。
  • 避免对所有错误无差别重试。
  • 考虑请求是否可能重复执行,以及是否存在重复扣费。

4. 管理上下文长度

不需要每次都把完整聊天历史传给模型。

可以根据业务选择:

  • 保留最近的若干轮对话。
  • 将旧对话压缩成摘要。
  • 只检索与当前问题相关的历史信息。
  • 对过长的用户输入和检索结果设置上限。

5. 设置预算与调用上限

在 Agent 中设置最大循环次数、工具调用次数和任务总预算。即使模型持续提出新任务,也不能让循环无限进行。

对于涉及用户配额的系统,还应在服务端记录实际使用量,并在并发请求场景中保证配额扣减的一致性。

6. 记录必要的指标

建议至少监控:

  • 模型请求次数。
  • 请求成功率和错误类型。
  • 请求耗时。
  • 输入、输出 Token 数。
  • 重试次数。
  • Agent 执行轮数。
  • 每个用户或业务模块的成本。

这些指标能帮助你定位:到底是 Prompt 太长、历史管理不合理、模型响应慢,还是 Agent 进行了过多的调用。

七、把第一阶段知识串起来

到这里,我们已经掌握了构建 AI 应用所需要的第一批基础知识。接下来用一个完整流程,把它们联系起来。

假设你正在为博客系统开发一个 AI 技术问答功能。

步骤 1:接收用户问题

Gin 接口接收问题,校验用户身份、输入长度和请求参数。

步骤 2:组织 Prompt 和上下文

System 设定助手规则,User 提供问题,必要时携带历史对话和检索资料。

步骤 3:调用 LLM

模型根据输入逐步生成 Token,生成参数影响采样过程和输出长度。

步骤 4:处理结构化结果

如果业务需要 JSON,使用结构化输出能力,并在 Go 中解析和校验。

步骤 5:执行可靠性与安全检查

处理错误、超时、成本限制和权限控制;需要时通过检索与程序测试验证答案。

步骤 6:返回用户

Gin 返回答案,并根据需要保存会话、记录使用量和监控指标。

你可以发现,AI 应用并不是把传统后端换成大模型,而是在原有后端架构中加入模型调用、上下文管理和结果验证等能力。

八、第一阶段学习进度总结

课程 已学习的内容
第 1 课 AI 应用与传统后端的区别,LLM、Tool Calling、Agent、RAG、MCP、Eino 的关系
第 2 课 LLM 的训练与推理、Token 生成机制、幻觉的基本概念
第 3 课 Token、上下文窗口、历史管理和调用成本
第 4 课 Prompt、System/User/Assistant 消息角色、多轮上下文
第 5 课 Temperature、Top-P、最大输出 Token 数和 Stop
第 6 课 JSON 结构化输出、Go 解析与业务校验
第 7 课 幻觉与能力边界、可靠性设计、成本控制

目前已经完成的代码实验有:

  • 使用 Go 结构体定义生成参数并序列化为 JSON。
  • 使用 encoding/json 解析模型响应。
  • 对结构化结果进行字段校验和业务规则校验。

这些实验都是本地模拟,没有调用真实大模型 API。建议你也亲手跑一遍,再进入第二阶段。

九、阶段复习:检查是否真正掌握

先回答下面 3 道综合题。如果某一题卡住,说明对应的知识点还需要回看。

练习 1:架构设计

你要为博客系统增加 AI 文章问答功能。用户提出自然语言问题,系统需要查询已有文章、组织答案并返回结果。请简要说明 LLM 和 Go 后端各自负责什么。

参考思路:LLM 负责"理解与表达"------把用户口语化的问题变成检索意图,再根据检索到的文章内容组织成通顺答案;Go 后端负责"确定性与边界"------鉴权、参数校验、按意图查 MySQL 拿到文章、把文章内容拼进上下文、控制 Token 预算、解析与校验模型返回、记录日志和用量。一句话:LLM 决定"话怎么说",Go 后端决定"能看什么、能给什么"。

练习 2:可靠性

模型返回了语法正确的 JSON,但其中的技术结论是错误的。为什么 json.Unmarshal 无法解决这个问题?你会增加哪些措施?

参考思路 :json.Unmarshal 只做"字节 → 结构体"的语法与类型转换,它对内容真假一无所知,所以它能挡住 {category: redis} 这种坏格式,但挡不住 {"category":"mysql","summary":"Redis 是关系型数据库"}。补的措施:RAG 提供可核查来源、规则交叉校验、关键结论人工确认、以及把失败样本沉淀成评测集持续回归。

练习 3:成本估算

假设输入价格为每百万 Token 1 美元,输出价格为每百万 Token 4 美元。某次调用输入 5,000 Token、输出 1,000 Token。如果调用 1,000 次,总成本是多少?Agent 为什么可能比单轮问答更贵?

参考思路 :单次 0.005 + 0.004 = 0.009 美元,1,000 次 = 9 美元。Agent 更贵是因为它把一次问答拆成多轮模型调用,每一轮输入里往往还要重复携带历史与工具结果,调用次数和单次输入长度同时上升,成本是乘法关系而非加法。所以 Agent 必须配最大迭代次数、Token 预算和超时上限。

十、下一阶段:Go 调用真实大模型 API

第二阶段将从概念进入实战,课程顺序是:

  1. 通过 HTTP 理解模型 API 的请求与响应。
  2. 使用 Go 发起真实模型调用。
  3. 通过环境变量管理 API Key。
  4. 设计模型请求与响应结构。
  5. 实现流式输出与多轮对话。
  6. 使用 Context 管理超时和取消。
  7. 实现有限重试、错误处理、日志与模型适配层。

我们会优先用标准库完成最小可运行的调用,再根据需要引入 SDK 或 Eino,不会一开始就引入一堆框架。

进入真实调用前有一个实际问题:如果暂时没有可用的大模型 API Key,也可以先通过模拟客户端把请求、响应和错误处理设计好,再接入实际服务,不需要公开或发送你的密钥。


下一篇:Go AI Agent 实战 08|HTTP 模型 API 的工作原理与请求流程

相关推荐
喵个咪1 小时前
GoWind UBA 拆解:把 Doris UNIQUE KEY 翻译成 ClickHouse——读数正确性对齐实录
大数据·后端·go
richdata1 小时前
鞋服品牌的商品计划是如何影响企业现金流的?
大数据
dghongcheng1 小时前
工业涂装数字化转型:从经验喷涂到数据驱动
人工智能·喷涂·喷漆设备·自动喷涂线·自动喷涂
liuyanqun-parbie1 小时前
从零设计一个通用智能电话平台:FreeSWITCH + ESL + AI 实战架构
人工智能·架构
文慧的科技江湖1 小时前
2026年10月21日智慧停车行业早报:番禺把单次封顶从132元砍到58元,同一天黄埔要往下挖59米只放200个车位——收费在往下走,车位在往深处长
人工智能·开源·智慧城市·智慧停车·城市管理·静态交通·停车saas
comedate1 小时前
【AI】Jev API 接入实战:用 Python 调用 TypeSafe Jev 做结构化判断
人工智能·python·jev·typesafe·快速判断模型
workflower1 小时前
无人机注册量与飞行量
大数据·网络·人工智能·云计算·汽车·无人机
鶴哥只手遮天1 小时前
Spring AI Alibaba 深度技术系列-第 05 章 编译与执行引擎:CompiledGraph、GraphRunner与三段式 Executor
java·人工智能·开源
灵动的艺术1 小时前
如一 Agent 架构解读(六):阈值、联动与坑位——压缩系统的肌理
人工智能·agent·如一