LLM 项目阅读实战:从请求追到模型与评测

# LLM 项目阅读实战:从请求追到模型与评测

本篇目标

建立阅读陌生 LLM 应用的固定顺序,从启动入口追踪一条请求,找出 Prompt、模型配置、上下文、输出校验、费用和评测之间的真实关系。

找到模型入口追踪上下文来源检查失败边界形成项目表达

# 先记住一句话

阅读 LLM 项目不要先通读所有 Prompt,而要先选一条真实业务请求,沿 “接口 → 业务用例 → 上下文 → 模型客户端 → 输出校验 → 持久化与评测” 追到底。

# 先回答十个问题

  1. 应用从哪个命令和文件启动?
  2. 模型客户端在哪里创建,密钥和模型名从哪里读取?
  3. 哪个接口或任务真正发起模型请求?
  4. Instructions、用户输入、历史和检索资料分别从哪里来?
  5. 输入怎样计算 Token、裁剪和脱敏?
  6. 输出是普通文本还是 Schema,谁负责业务校验?
  7. 超时、取消、限流和重试在哪里处理?
  8. 模型结果怎样保存,怎样避免重复调用和旧结果覆盖?
  9. 日志记录哪些模型、延迟、Token、费用和错误信息?
  10. 哪套离线评测和线上指标证明修改没有回退?

能用一条调用链回答这十个问题,才算真正看懂项目。

# 一个常见目录怎样阅读

app/
├── main.py                  # Web 应用入口与生命周期
├── api/summaries.py         # HTTP 输入、认证和取消
├── services/summarizer.py   # 摘要业务规则
├── llm/client.py            # 模型 SDK、超时和响应解析
├── llm/prompts.py           # Instructions 与 Prompt 版本
├── retrieval/search.py      # 检索、权限过滤和引用
├── repositories/notes.py    # 原文与摘要持久化
└── schemas/summary.py       # 输入输出 Schema
evals/
├── cases.jsonl              # 固定真实任务
├── graders.py               # 确定性和语义评分
└── run.py                   # 运行并生成对比报告
1
2
3
4
5
6
7
8
9
10
11
12
13

目录名不是标准。真正要看的是依赖和数据流,不要看到 llm/ 文件夹就假设所有模型逻辑都在那里。

# 第一步:从启动命令找到组合根

先查看 README、容器命令、进程配置或部署文件,找到真正入口。组合根负责创建并连接:

  • 配置与密钥提供器;
  • 数据库和向量库客户端;
  • 模型客户端;
  • Repository 与业务 Service;
  • HTTP 路由或任务 Worker;
  • 日志、Tracing 和关闭逻辑。

如果模型客户端在每个请求里重新创建,要检查连接复用和资源生命周期;如果全局对象保存用户请求状态,则要检查并发污染。

# 第二步:选一条业务请求追到底

以 “为用户笔记生成摘要” 为例:

POST /notes/{id}/summary
  ↓ 认证并解析 note_id
SummaryService.generate(user_id, note_id)
  ↓ Repository 按 user_id + note_id 读取原文和版本
PromptBuilder.build(note)
  ↓ 计算 Token 并生成 Instructions + Input
ModelClient.summarize(request)
  ↓ 超时、限流、调用模型、解析 Schema
SummaryService 校验结果
  ↓ 按原文版本和幂等键写回
返回摘要、模型版本和任务状态
1
2
3
4
5
6
7
8
9
10
11

重点检查用户身份是否一直传到数据访问层。只在路由认证、随后按 note_id 查询,会留下越权读取风险。

# 第三步:展开模型请求的全部来源

不要只看最终 Prompt 字符串,要标出每块内容的来源和可信度:

内容 来源 主要风险
稳定 Instructions 版本化代码 多处重复、规则冲突
用户正文 数据库或请求 Prompt Injection、超长、隐私
历史对话 会话存储 过期、跨用户混入
RAG 证据 检索系统 权限泄漏、错误召回
工具结果 外部服务 失败结果被当成功
输出 Schema 应用代码 只校验格式、不校验业务

用户正文和检索文档属于待处理数据,不应覆盖开发者规则。拼接时要保留清晰边界,并在宿主代码中强制权限和操作限制。

# 第四步:看模型客户端隐藏了什么

模型客户端应该统一处理:

  • 提供方 SDK 和模型参数;
  • 请求超时和取消;
  • 错误分类、限流提示和有限重试;
  • 普通文本、流式事件或结构化结果解析;
  • 请求 ID、Usage 和完成状态;
  • 不含敏感正文的必要观测数据。

但它不应决定 “用户能否访问某条笔记” 或 “摘要能否覆盖新版本正文” ,这些是业务和数据边界。

# 第五步:检查输出怎样进入业务

结构化输出通过 Schema 后,还要检查:

  • 引用是否指向真实资料;
  • 分类值是否符合当前业务状态;
  • 模型是否明确拒绝或被截断;
  • 原文版本是否在生成期间变化;
  • 同一任务是否已经写入结果;
  • 内容是否需要安全过滤或人工审核。

模型成功、数据库写入失败时会出现不确定状态。任务应有幂等键和状态记录,重试前先查询已有结果,不能无条件再次调用模型。

# 第六步:把测试和评测分开看

验证方式 主要验证什么
单元测试 Prompt Builder、Token 预算、错误映射和业务分支
集成测试 模型客户端适配、数据库、向量库和 HTTP 契约
合约测试 Fake 响应、拒绝、截断、限流和 Schema 变化
离线评测 摘要忠实度、抽取正确率和安全行为
线上监控 延迟、Token、费用、失败率和用户反馈

测试通过只能说明程序按预期运行,不代表模型回答质量足够;几条回答看起来不错,也不能证明取消、权限和写回路径正确。

# 搜索陌生项目时的实用顺序

# 找模型 SDK 和请求入口。
rg "responses.create|responses.parse|chat.completions|generateContent|invoke" .

# 找模型名、Prompt 和输出预算的来源。
rg "model=|MODEL_|instructions|system|temperature|max_output" .

# 找流式、超时、重试和取消。
rg "stream|timeout|retry|backoff|cancel" .

# 找 Token、费用和评测记录。
rg "usage|token|cost|eval|grader|dataset" .
1
2
3
4
5
6
7
8
9
10
11

这些关键词只是入口。找到候选后仍要沿函数调用和依赖注入确认真实路径,不能把搜索命中当作已执行行为。

# 常见危险信号

  • API Key 写在源码或前端;
  • 每次请求都创建新的网络客户端;
  • Prompt、模型名和参数散落在多个路由;
  • 自动截断时可能删除权限或关键业务条件;
  • 捕获所有异常后统一再次调用模型;
  • 只要求返回 JSON,却没有 Schema 和解析失败路径;
  • 日志保存完整私密 Prompt;
  • 没有请求取消,用户断开后仍继续生成;
  • 没有模型与 Prompt 版本,线上变化无法回溯;
  • 只有演示样例,没有固定评测集。

# 项目面试怎样表达

我阅读 LLM 项目时先从启动命令找到模型客户端、数据库和检索组件怎样组装,再选择一条核心请求追踪用户身份、Prompt 来源、Token 预算、模型调用、输出校验和写回。模型调用按不稳定外部依赖处理,设置总超时、取消、有限重试和并发上限;结构化输出通过 Schema 后仍做业务校验。最后用请求 ID 串联模型版本、延迟、Token 和错误,并检查固定评测集是否覆盖真实失败。

继续追问时,应能回答:

为什么 Prompt 不应该散落在路由中?参考答案

Prompt 是会影响业务结果的版本化逻辑,散落在路由会造成重复、冲突和无法统一评测。应把稳定指令和动态组装集中到明确模块,记录版本并通过代码审查和回归测试修改。

模型成功后为什么还要做业务校验?参考答案

API 成功和 Schema 合法只说明调用与格式完成,不能保证引用真实、金额正确、资源有权限或数据版本未变化。关键条件必须由应用结合真实状态再次判断。

怎样判断性能问题在应用还是模型提供方?参考答案

把总耗时拆成应用排队、检索、模型首 Token、模型生成和数据库写回,并用同一个请求 ID 串联 Trace。再结合输入输出 Token、模型版本和提供方请求 ID,才能判断慢在本地还是远端。

测试和模型评测有什么区别?参考答案

测试主要验证代码契约、分支和外部组件集成是否正确;模型评测关注回答质量、安全、延迟和费用。两者都需要,测试通过不能证明生成质量好,评测分数高也不能证明权限与事务实现正确。

# 高频面试题与回答

1. 接手陌生 LLM 项目先看哪里?参考答案

先从启动命令找到配置、模型客户端、数据库和检索组件的组合关系,再选一条核心请求沿接口、业务、Prompt、模型、校验和写回追到底。最后检查超时重试、权限、用量记录和评测集。

2. LLM 项目最容易遗漏的生产风险是什么?参考答案

常见风险是把模型当作普通确定性函数:没有总超时和取消,超时后无条件重试,输出通过格式检查就直接写库,也没有记录模型与 Prompt 版本。这会同时放大费用、数据错误和排障难度。

3. 怎样证明一次模型升级可以上线?参考答案

用固定真实评测集与旧版本比较质量、安全、延迟和费用,并检查不同任务和风险切片。达到门禁后先小流量发布,监控线上错误与用户反馈,同时保留旧模型和 Prompt 的快速回退能力。

# 接下来学什么

完成本模块后,继续学习 Agent 开发总览,理解怎样在模型调用之上加入工具、状态、循环决策和人工控制。

# 参考资料