模型读写文本的单位
你输入一句话,模型会先切成 token,再把 token 转成数字。生成时也是一个 token 一个 token 往外吐。
这三个概念应该放在一起学。Token 是模型读写文本的单位,上下文窗口决定模型这次能看到多少内容,幻觉则常常发生在信息不足、检索不准或输出没有校验的时候。
很多 LLM 问题都能回到这三件事:模型看到了什么,能看多少,看到的信息是否足够可靠。只要这个框架立起来,Prompt、RAG、Agent、评测都会更容易理解。
你输入一句话,模型会先切成 token,再把 token 转成数字。生成时也是一个 token 一个 token 往外吐。
系统提示、用户问题、历史消息、检索资料、工具结果,都要装进上下文窗口。
模型可能编字段、编接口、编来源、编结论。企业应用里要把它当成设计风险处理。
Token 可以是一个字、一个词、一个子词、一个标点,也可能是代码里的片段。不同模型的 tokenizer 不一样,所以同一段文本在不同模型里可能切出不同数量的 token。
请根据商品录入系统的字段规则,生成批量导入异常处理说明。
LLM 处理代码时,同样先切分。变量名、符号、缩进、字符串都可能影响 token 数。
function validateSku(row) {
if (!row.sku || row.sku.length > 64) {
return "SKU_INVALID";
}
}
很多模型按输入 token 和输出 token 计费。日志、历史对话、检索文档塞得越多,成本越高。
输入越长,模型要处理的上下文越大;输出越长,生成循环越多。延迟通常会随之增加。
上下文里无关内容太多,模型更难抓重点。不是越多越好,而是要放对内容。
程序员不会把无限数据塞进内存,也不该把所有文档都塞进 prompt。上下文窗口有上限,输出也要占空间。实际工程里,要提前做 token 预算。
const maxWindow = 32000;
const outputBudget = 4000;
const inputBudget = maxWindow - outputBudget;
const context = buildContext({
systemPrompt,
latestUserMessage,
retrievedDocs: pickTopK(docs, inputBudget),
chatHistory: summarizeIfNeeded(history)
});
LLM 没有自动读取你硬盘、数据库、公司文档的能力。它能参与本次生成的内容,必须通过 prompt、历史消息、RAG、工具结果等方式放进上下文。
窗口越大,能放的材料越多,但这不等于效果一定更好。企业应用里通常要按任务分配预算:系统提示占多少,RAG 占多少,历史占多少,输出预留多少。
这个比例不是标准答案。写 PRD、写代码、做客服问答,预算会不同。
| 场景 | 应该多给谁 | 容易出的问题 | 处理方式 |
|---|---|---|---|
| 生成企业 PRD | 历史需求、系统字段、业务规则 | 编不存在的字段或流程 | RAG 加字段校验,缺资料写入待确认项。 |
| 代码解释 | 相关文件、调用链、错误日志 | 看不到关键依赖,解释偏离真实代码 | 只放相关片段,必要时用工具查文件。 |
| 客服问答 | 用户订单状态、政策文档 | 回答过期政策或猜订单状态 | 实时接口查询加政策版本号。 |
| 结构化抽取 | 输入原文和 schema | 输出 JSON 不合法或字段乱填 | JSON Schema 校验,失败重试或转人工。 |
长上下文很有用,但它不是银弹。资料放得太多,模型可能忽略中间内容、被无关片段干扰,或者在多个冲突来源之间选错。
有些模型对开头和结尾更敏感。关键约束放在中间,可能被弱化。
把整本手册塞进去,模型不一定更准。它可能抓到相似但不适用的段落。
两份文档说法不同,如果没有版本和优先级,模型可能挑一个看起来顺的答案。
输出格式、禁止编造、版本优先级,尽量放在靠近用户任务的位置。
同一个规则有多个版本时,要告诉模型哪个版本优先。
不要先把所有资料总结成一坨。先找相关片段,再做面向问题的摘要。
幻觉不一定是胡言乱语。麻烦的幻觉往往很像正确答案:字段名像真的,接口路径像真的,引用来源像真的,业务结论也像真的。
用户问:“商品导入失败时,有没有错误明细下载接口?”
模型回答:
有,接口是 GET /api/product/import/errors/{taskId}
返回字段包括 rowNumber、sku、errorMessage。
问题是:公司系统里根本没有这个接口。它只是符合常见命名习惯。
模型的目标是生成合适的下一个 token。它不是天然的事实校验器。只要任务要求它给出完整答案,但上下文又不够,它就可能用模式补洞。
用户问内部系统细节,但上下文没有接口文档、字段表或历史需求,模型就容易猜。
RAG 查到了旧版本文档或相邻系统文档,模型基于错误材料回答。
比如“为什么系统支持自动退款”,但系统并不支持。模型可能顺着问题解释。
temperature 设置较高时,输出更有变化,也更可能偏离事实。
模型为了完成任务,会把不确定内容写成肯定句。
字段、接口、金额、权限点如果不校验,错误会直接进入业务流程。
“不要幻觉”这句话有用,但远远不够。企业应用要把资料来源、输出格式、校验规则、失败路径都设计进去。
如果资料中没有明确依据,不要补全。
把缺失信息写入 openQuestions。
每条业务规则都要给 sourceId。
输出必须符合 JSON Schema。
assertValidJson(output);
assertFieldsExist(output.fields, schemaRegistry);
assertApisExist(output.apis, openApiSpec);
assertEveryRuleHasSource(output.rules);
routeToReviewIfRisky(output);
假设用户要生成“商品批量导入”的需求说明。模型如果只凭经验写,会写得很顺,但很可能不符合企业系统现状。正确做法是先组织上下文,再生成,再校验。
| 模型可能乱写 | 为什么会发生 | 工程处理 |
|---|---|---|
| 编一个“错误明细下载接口” | 常见系统都有类似能力,但当前系统未必有。 | 拿接口路径去 OpenAPI 校验;没有就写成“待确认”。 |
| 把“价格”写成必填 | 模型按电商常识补全,但企业可能允许草稿商品无价格。 | 以字段字典和状态规则为准。 |
| 默认支持覆盖已有 SKU | 模型为了流程完整,自动补了危险操作。 | 高风险动作必须查权限和审批规则。 |
| 遗漏导入任务状态 | 上下文只给了字段,没给异步任务设计。 | Prompt 要要求输出状态机和失败重试。 |
这几个问题出现频率很高。不要只背定义,最好能结合上下文预算、RAG 和校验讲。
Token 是模型处理文本的基本单位,不一定等于字或词。模型输入和输出都会被切成 token。
它重要是因为上下文窗口、计费、延迟和输出长度都和 token 数有关。做 LLM 应用时,要估算输入、检索资料和输出预算,不能无限塞内容。
上下文窗口是模型在一次请求中能看到的 token 范围。系统提示、用户问题、历史对话、RAG 文档、工具结果和预留输出都会占窗口。
窗口外的内容不会自动参与生成。公司文档、数据库、代码仓库如果没有被检索或工具读取,模型就无法可靠使用。
不一定。长上下文能放更多资料,但也会增加成本和延迟。资料太多、太杂、互相冲突时,模型可能抓错重点。
更好的做法是按任务检索相关资料,保留来源和版本,把关键约束放近任务,并给输出留足 token。
幻觉是模型生成了看起来合理但不真实的内容。比如编造接口、字段、来源、政策、结论。
它通常发生在资料缺失、检索错误、问题诱导、采样发散或输出缺少校验时。工程上要用 RAG、工具查询、引用来源、结构化输出、程序校验和人工审核来降低风险。
我会先把知识库做成有来源、版本和权限的检索系统。用户提问后,先检索资料,再把最相关片段和问题一起放入上下文。Prompt 要要求模型只基于资料回答,缺信息就说明缺失。
输出侧要带 sourceId 或引用片段。涉及接口、金额、权限、订单状态等内容时,走工具查询或程序校验。高风险回答进入人工审核,并用线上反馈持续更新评测集。
写 Prompt 之前,先把这些问题过一遍。很多幻觉不是模型调用后才出现的,而是在上下文设计阶段就埋下了。
| 概念 | 一句话 | 工程检查点 |
|---|---|---|
| Token | 模型读写文本的片段单位。 | 输入、资料、历史、输出分别占多少? |
| 上下文窗口 | 模型本次请求能看到的 token 范围。 | 关键事实是否真的放进窗口? |
| 输出预算 | 给模型生成答案预留的 token 空间。 | 复杂 JSON 或长文档会不会被截断? |
| 长上下文 | 能放更多内容,但也可能引入噪声。 | 资料是否按相关性、版本和来源筛过? |
| 幻觉 | 看似合理但不真实的输出。 | 是否有引用、校验、待确认项和人工审核? |
| RAG | 推理时检索资料并放入上下文。 | 检索是否召回正确资料,是否带来源? |
| 结构化校验 | 用程序检查模型输出是否可用。 | 字段、接口、枚举、权限点是否存在? |