基础系列已经覆盖了 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 负责协议检查、文件读写和副作用控制。面对诊断类任务,最重要的不是让模型表现得“像专家”,而是保留证据、标明不确定性,并让最终行动仍处在人的控制之下。