基础系列已经覆盖了 API 调用、消息历史、上下文、生成参数、结构化输出、错误处理、提示词和评估。本文继续做一个小而完整的综合项目:输入一段应用日志,让模型提取可能的故障症状、证据和下一步检查建议,最后由 Python 校验并保存为 JSON 报告。工具只读日志、只给建议,不会自动执行命令或修改系统,重点是把不确定的模型判断变成可复核的工程产物。

先确定输入、输出和边界

日志诊断适合让模型做信息整理和初步归因,但不应该让模型直接重启服务、删除文件或修改配置。一个安全的最小流程是:读取日志文本,调用模型生成候选报告,校验报告结构,再把报告交给人确认。

本例约定输出包含四个字段:summary 是现象概括,severity 是严重程度,evidence 是日志中实际出现的证据列表,next_checks 是下一步检查建议列表。severity 只能是 low、medium 或 high。如果日志没有足够信息,模型必须明确表示无法确定,而不是补造根因。

准备环境和示例日志

在项目虚拟环境中安装官方 Python SDK:

1
2
3
python -m venv .venv
source .venv/bin/activate
python -m pip install openai

准备一个 app.log,内容可以是你自己的测试日志,例如:

1
2
3
2026-10-18T07:20:01Z INFO starting worker
2026-10-18T07:20:03Z ERROR database connection failed: timeout
2026-10-18T07:20:03Z WARN retry scheduled in 5 seconds

密钥和模型名只从环境变量读取:

1
2
export OPENAI_API_KEY="替换为你的真实密钥"
export MODEL_NAME="替换为你可用的模型名称"

模型名称、服务地址和结构化输出的具体支持情况会随服务变化。运行前应查阅所用模型服务的官方文档;下面的示例使用当前 OpenAI Python SDK 的 responses.create 和 output_text,并在本地再次解析 JSON。即使服务端提供了更强的结构化约束,客户端校验也不应省略。

编写诊断报告器

新建 diagnose_log.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import json
import os
import sys
from pathlib import Path
from typing import Any

from openai import OpenAI


SEVERITIES = {"low", "medium", "high"}


def validate_report(value: Any) -> dict[str, Any]:
if not isinstance(value, dict):
raise ValueError("报告顶层必须是对象")
required = {"summary", "severity", "evidence", "next_checks"}
if set(value) != required:
raise ValueError("报告字段必须恰好是 summary、severity、evidence、next_checks")
if not isinstance(value["summary"], str) or not value["summary"].strip():
raise ValueError("summary 必须是非空字符串")
if value["severity"] not in SEVERITIES:
raise ValueError("severity 不是允许的值")
for field in ("evidence", "next_checks"):
items = value[field]
if not isinstance(items, list) or not all(
isinstance(item, str) and item.strip() for item in items
):
raise ValueError(f"{field} 必须是非空字符串数组")
return value


def diagnose(log_text: str) -> dict[str, Any]:
if not log_text.strip():
raise ValueError("日志不能为空")

api_key = os.environ.get("OPENAI_API_KEY")
model = os.environ.get("MODEL_NAME")
if not api_key or not model:
raise RuntimeError("请设置 OPENAI_API_KEY 和 MODEL_NAME")

client = OpenAI(api_key=api_key)
prompt = (
"分析下面的应用日志,只返回一个 JSON 对象,不要 Markdown 代码围栏。"
"字段必须为 summary、severity、evidence、next_checks。"
"severity 只能是 low、medium、high。"
"evidence 只能引用日志中确实出现的信息;无法确定根因时要明确说明。"
"不要提出执行危险操作的建议。\n\n日志:\n" + log_text
)
response = client.responses.create(
model=model,
instructions="你是谨慎的值班诊断助手,区分事实、推测和待验证事项。",
input=prompt,
)
return validate_report(json.loads(response.output_text))


def main() -> None:
if len(sys.argv) != 3:
raise SystemExit("用法:python diagnose_log.py app.log report.json")
log_path, report_path = map(Path, sys.argv[1:])
report = diagnose(log_path.read_text(encoding="utf-8"))
report_path.write_text(
json.dumps(report, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
print(f"已保存诊断报告:{report_path}")


if __name__ == "__main__":
main()

运行:

1
python diagnose_log.py app.log report.json

validate_report 是这个示例的关键。json.loads 只保证返回文本语法正确,并不能保证字段正确;显式检查字段集合、枚举值和数组元素,才能让下游程序放心读取。报告写入新的 report.json,不会覆盖原始日志,也不会把模型建议当作已经执行的事实。

如何做无网络验证

没有密钥时仍然可以验证大部分代码。把 validate_report 单独拿出来,用固定 Python 对象测试:完整报告应通过;缺少 evidence、使用未知严重程度、数组中混入数字,都应抛出 ValueError。还可以用 json.dumps 和 json.loads 往返一次,确认中文内容不会被破坏。

真实请求只负责验证服务连接和模型输出协议,不要把某一次生成结果写成程序保证。建议准备三组样例:正常启动日志、明确错误日志、只有警告但没有根因的日志,然后人工检查证据是否真的来自输入。若模型经常输出额外字段,可进一步使用服务支持的 JSON Schema 约束,但客户端校验仍然保留。

常见问题

为什么不让程序自动执行 next_checks? 日志可能包含恶意或误导内容,模型也可能把高风险操作写进建议。当前程序只生成报告;如果以后接入工具,必须增加白名单、参数校验和人工审批。

模型说“数据库故障”,但日志只有 timeout,怎么办? 这就是证据和推测的区别。提示词要求 evidence 只能引用原文,程序还可以要求报告增加 confidence,并把没有直接证据的结论标记为待验证,而不是当成事实展示。

日志中有密钥怎么办? 调用前先做脱敏,至少处理令牌、密码、Cookie 和个人信息。不要为了调试把完整日志写入仓库、打印到终端或提交给第三方服务。脱敏规则也应配套测试,不能只依赖模型自己发现敏感信息。

日志很长会怎样? 全部放入一次请求会受到上下文窗口限制,也可能增加成本。实际系统应按时间段或请求 ID 分块,保留文件名、行号和时间范围,再汇总各块报告;不要简单截断开头或结尾后声称已经分析全文。

小结

这个小项目把日志读取、提示词约束、模型调用、JSON 解析、枚举校验和安全边界串成了一条可运行链路。模型负责整理线索和提出待验证方向,Python 负责协议检查、文件读写和副作用控制。面对诊断类任务,最重要的不是让模型表现得“像专家”,而是保留证据、标明不确定性,并让最终行动仍处在人的控制之下。