系列基础内容已经覆盖了模型调用、消息组织、提示词、结构化输出、错误处理和结果评估。本篇做一个综合小项目:把英文技术说明翻译成中文,同时由程序检查术语表中的固定译法是否被保留。它不是“把文本交给模型就结束”,而是把模型生成、规则校验和人工确认拆成清晰的步骤。
先定义输入、输出和边界 输入包含原文和术语表。术语表把英文词组映射到项目约定的中文表达,例如 embedding 必须翻译为“嵌入”,context window 必须翻译为“上下文窗口”。输出包含译文以及模型认为实际使用到的术语列表。
程序只负责生成候选译文和发现明显违规,不自动覆盖原文,也不证明译文在专业语境中一定正确。术语匹配是确定性规则,语言是否自然仍需要人工阅读。这个边界很重要:模型适合处理语言转换,代码适合检查不能含糊的约束。
准备最小环境 在独立虚拟环境安装官方 Python SDK:
1 2 3 python -m venv .venv source .venv/bin/activatepython -m pip install openai
密钥和模型名只能从环境变量读取:
1 2 export OPENAI_API_KEY="替换为你的真实密钥" export MODEL_NAME="替换为你可用的模型名称"
新建 translation_case.json:
1 2 3 4 5 6 7 8 { "source" : "An embedding maps text to a vector. The context window limits the input." , "glossary" : { "embedding" : "嵌入" , "context window" : "上下文窗口" , "vector" : "向量" } }
编写翻译和校验程序 创建 translator.py。示例使用 Responses API,并要求模型只返回 JSON。即使接口请求成功,json.loads 和本地规则检查仍然不可省略,因为“请求成功”不等于“内容符合协议”。
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 jsonimport osimport sysfrom pathlib import Pathfrom openai import OpenAIdef load_case (path: Path ) -> tuple [str , dict [str , str ]]: data = json.loads(path.read_text(encoding="utf-8" )) source = data.get("source" ) glossary = data.get("glossary" ) if not isinstance (source, str ) or not source.strip(): raise ValueError("source 必须是非空字符串" ) if not isinstance (glossary, dict ) or not glossary: raise ValueError("glossary 必须是非空对象" ) if not all (isinstance (k, str ) and isinstance (v, str ) and k.strip() and v.strip() for k, v in glossary.items()): raise ValueError("术语表的键和值都必须是非空字符串" ) return source, glossary def validate (result: object , glossary: dict [str , str ] ) -> dict [str , object ]: if not isinstance (result, dict ): raise ValueError("模型结果必须是对象" ) translation = result.get("translation" ) used_terms = result.get("used_terms" ) if not isinstance (translation, str ) or not translation.strip(): raise ValueError("translation 必须是非空字符串" ) if not isinstance (used_terms, list ) or not all (isinstance (x, str ) for x in used_terms): raise ValueError("used_terms 必须是字符串数组" ) expected = set (glossary.values()) unknown = set (used_terms) - expected if unknown: raise ValueError(f"used_terms 含有术语表之外的词:{sorted (unknown)} " ) missing = [zh for en, zh in glossary.items() if en.lower() in source_text.lower() and zh not in translation] if missing: raise ValueError(f"译文缺少必须使用的术语:{missing} " ) return {"translation" : translation, "used_terms" : used_terms} source_text = "" def main () -> int : global source_text if len (sys.argv) != 2 : print ("用法:python translator.py translation_case.json" , file=sys.stderr) return 2 source_text, glossary = load_case(Path(sys.argv[1 ])) glossary_text = json.dumps(glossary, ensure_ascii=False ) instructions = ( "你是技术文档翻译助手。将 SOURCE 翻译为中文,并严格使用 GLOSSARY 中的中文译法。" "只返回 JSON 对象,字段必须是 translation 和 used_terms。" "used_terms 只能列出实际使用的术语中文值,不要输出 Markdown。" ) prompt = f"GLOSSARY:\n{glossary_text} \n\nSOURCE:\n{source_text} " response = OpenAI().responses.create( model=os.environ["MODEL_NAME" ], instructions=instructions, input =prompt, ) result = validate(json.loads(response.output_text), glossary) print (json.dumps(result, ensure_ascii=False , indent=2 )) return 0 if __name__ == "__main__" : raise SystemExit(main())
load_case 检查输入协议,避免把错误的 JSON 直接送给模型。validate 则检查三个层次:结果是不是对象,字段类型是否正确,译文是否包含原文中出现的术语对应译法。示例把 source_text 作为校验上下文传入,是为了让检查逻辑知道哪些术语确实出现在本次原文中;更大的程序可以把原文作为参数传给校验函数,避免全局变量。
运行:
1 python translator.py translation_case.json
本文不伪造运行结果。实际译文取决于密钥、模型和服务端返回;若返回内容缺少“上下文窗口”或“向量”,程序应直接报错,而不是打印一份看似正常的结果。
常见问题 为什么还要让模型返回 used_terms? 它可以作为可读的审查线索,但不是最终依据。真正的通过条件是程序根据原文、术语表和译文重新检查,不能只相信模型自报的列表。
术语表很长怎么办? 先按文档类型拆分术语表,只把本篇可能用到的部分放入上下文。术语过多会增加输入长度,也会让模型更难区分相近表达;分块翻译时要在每块使用同一版本的术语表。
规则检查通过就可以自动发布吗? 不可以。规则只能发现缺词、错词和格式问题,不能判断语气、歧义、数字含义或上下文是否准确。涉及 API 说明、命令和安全操作时,至少保留人工复核步骤。
模型返回了 Markdown 代码围栏怎么办? 可以在有限次数内请求修复,但不要无条件剥离任意文本。更稳妥的方式是记录原始响应,先解析并校验;多次失败就停止,让调用方处理,而不是默默猜测 JSON 内容。
小结 这个项目把一次翻译调用变成了可验证流水线:输入校验保证边界,提示词传递任务和术语约束,模型生成候选译文,Python 再检查结构与固定词汇,最后由人确认语言质量。综合项目的重点不是增加代码量,而是明确哪些判断交给模型、哪些判断必须由程序完成。只要把模型输出当作不可信输入,AI 功能就更容易测试、审计和维护。