【技术专栏】 AI开发
【内容摘要】 综合运用结构化输出、校验和人工审批,构建一个只生成草稿、不直接发布的 AI 工具。
本篇把模型调用、结构化输出和人工审批组合成小项目:输入变更摘要,生成草稿,校验后等待确认。
功能边界
模型只改写事实,不得补充不存在的功能。输出固定为 title、summary 和 items。提示词不是边界,JSON 检查和人工确认才是。
准备环境
1 2 3
|
python -m venv .venv source .venv/bin/activate python -m pip install openai python-dotenv
|
1 2 3
|
OPENAI_API_KEY=替换为你的真实密钥 MODEL_NAME=替换为你可用的模型名称 OPENAI_BASE_URL=
|
最小实现
新建 release_notes.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
|
import json, os, sys from pathlib import Path from dotenv import load_dotenv from openai import OpenAI
load_dotenv() client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"), base_url=os.getenv("OPENAI_BASE_URL") or None) model = os.environ["MODEL_NAME"] allowed = {"feature", "fix", "change", "breaking"} rules = "只返回 JSON,字段为 title、summary、items;每项为 type、text、needs_attention。type 只能是 feature/fix/change/breaking,只改写输入事实。"
def check(raw): try: data = json.loads(raw) except json.JSONDecodeError as e: raise ValueError("返回不是 JSON") from e if set(data) != {"title", "summary", "items"} or not data["items"]: raise ValueError("顶层字段无效") if not all(isinstance(data[k], str) and data[k].strip() for k in ("title", "summary")): raise ValueError("标题或摘要为空") for x in data["items"]: if set(x) != {"type", "text", "needs_attention"} or x["type"] not in allowed: raise ValueError("条目字段无效") if not isinstance(x["text"], str) or not x["text"].strip() or not isinstance(x["needs_attention"], bool): raise ValueError("条目类型无效") return data
def main(): if len(sys.argv) != 2: raise SystemExit("用法:python release_notes.py change-summary.txt") source = Path(sys.argv[1]).read_text(encoding="utf-8") if not source.strip() or len(source) > 8000: raise SystemExit("输入为空或过长") r = client.responses.create(model=model, instructions=rules, input=source) draft = check(r.output_text) print(json.dumps(draft, ensure_ascii=False, indent=2)) if input("确认保存?[y/N] ").lower().strip() == "y": Path("release-notes.json").write_text(json.dumps(draft, ensure_ascii=False, indent=2), encoding="utf-8") print("已保存")
if __name__ == "__main__": main()
|
准备 change-summary.txt:
1
|
新增 CSV 导出;修复空筛选条件报错;CSV 暂不支持自定义列顺序。
|
执行 python release_notes.py change-summary.txt。非法 JSON、缺字段、错误类型会在保存前被拒绝,输入 n 不会写文件。
常见问题
为什么提示词要求 JSON 后仍要校验? 提示词只是引导,程序必须拒绝未知字段、空文本和错误枚举。
调用失败怎么办? 增加超时和有限次数的指数退避,区分认证、限流、网络错误;失败时不要写入空草稿。
小结
这个项目形成了“准备事实—请求模型—校验结构—人工确认”的闭环。模型负责改写,Python 负责类型和副作用;职责分开才能让原型可维护。
技术分享自:时光笔记 (wxy.email) | 华为云开发者社区
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
评论(0)