基于 MLflow 的提示词工程 基于 MLflow 的提示词工程1. 整体架构系统围绕MLflow Prompt Registry构建提示词版本管理的闭环。Registry 中为每个提示词维护独立的版本链v1 → v2 → v3 …各提示词独立优化、独立评估、独立迭代。版本迭代的核心引擎是MLflowoptimize_prompts()它接收三个组件完成闭环predict_fn封装 LLM 调用每次调用时从 Registry 内部加载当前版本的 Prompt接收输入数据返回模型生成的文本Scorers自定义评估器分为规则型纯算法零成本、确定性高和 LLM Judge 型调用 LLM 打分处理需要语义理解的维度两类可按需组合Optimizer分析每条训练数据的评分结果迭代修改 Prompt 模板以提升综合评分最终将优化后的模板自动注册为 Registry 中的新版本核心循环为train_data → predict_fn 生成 → scorers 评分 → optimizer 分析改进 → 新 Prompt → 重新生成 → … → 收敛或达到上限。整个闭环由 MLflow 驱动业务代码只需提供上述三个组件。2. MLflow Prompt Registry — 提示词版本管理2.1 为什么用 MLflow Registry 而非自建版本表mlflow.genai命名空间原生支持 Prompt 的注册、版本化、加载optimize_prompts()直接读写 Registry优化结果自动注册为新版本无需手动搬运版本追踪与 MLflow Tracking 联动每次优化自动关联 MLflow Run可回溯每次版本变更的评分变化支持 URI 引用prompts:/name/version与 MLflow 生态无缝集成2.2 核心 API基于mlflow.genai和MlflowClient操作MLflow API说明注册/更新mlflow.genai.register_prompt(name, template)不存在则创建 v1已存在则版本号 1获取mlflow.genai.load_prompt(name, version)version 为 None 时取最新版列出版本MlflowClient().search_prompt_versions(name)返回所有版本及其模板内容删除MlflowClient().delete_prompt(name)删除该 Prompt 的所有版本构建 URIfprompts:/{name}/{version}可加alias后缀引用别名2.3 对外 HTTP API将 Registry 操作封装为 REST 端点供前端版本管理页面调用方法路径说明POST/api/prompt-registry/register手动编辑 Prompt 后保存版本号 1POST/api/prompt-registry/get获取指定版本 Prompt默认最新POST/api/prompt-registry/versions列出所有版本前端展示版本历史POST/api/prompt-registry/delete删除 Prompt 所有版本3. 评估器设计3.1 注册与约定使用 MLflow 的mlflow.genai.scorers.scorer装饰器注册指定 name 参数。MLflow 优化器按名称发现 scorer。函数签名约定MLflow 调用时传入三个 kwarg ——outputs模型生成文本、expectations期望输出、inputs原始输入。返回值 0.0~1.0分数越高越好。同步要求scorer 必须是同步函数MLflow 优化器在同步上下文中运行。内部可调用外部 API但需使用同步客户端。3.2 两类评估器的分工规则型纯算法无 LLM 调用适合结构化、可量化、有明确对错标准的检查维度。优势是零成本、确定性高、速度快。典型模式包括正则提取 召回率、N-gram 覆盖率、结构特征比对。LLM Judge 型调用 LLM 打分适合需要语义理解、无法用规则穷举的维度。代价是每次评分消耗 token 且有随机性。实际使用中通常组合多类 scorer从不同维度综合评估生成质量。两类 scorer 的比例取决于场景——结构化输出任务偏规则型开放式创意任务偏 Judge 型。3.3 规则型评估器的典型模式加权实体召回率定义一组关键实体类型及其正则模式按重要性分配权重计算加权召回率。注意事项对数值做归一化如金额统一单位避免格式差异误判仅对参考文本中实际存在的实体类别计算空类别跳过参考文本全空时返回满分无法评估不惩罚多维结构评分将结构完整性拆解为多个可量化维度如标题覆盖率、顺序保持度、段落密度、长度比各自评分后加权求和。其中顺序检查可用 LIS最长递增子序列算法衡量生成文本是否保持了参考文本的章节顺序。IDF 加权覆盖率用 N-gram 做分词中文用字符级 N-gram西文单词保留引入 IDF 权重——频率越低的 N-gram 信息量越大、对评分影响越大。配合长度惩罚防止过短输出蒙混过关。3.4 LLM Judge 型评估器的设计要点调用参数temperature0.0消除随机性确保评分一致、max_tokens限制在仅够返回分数的量。Judge Prompt 设计模式角色设定 → 评分标准每维度含 0-10 分段锚点描述将抽象标准量化为具体阈值→ 输入材料截断到合理长度→ 输出指令仅输出整数。锚点是关键——例如6-7 分有 1-2 处非核心错误比6-7 分较好更容易让 LLM 打出一致分数。分数解析从 LLM 输出正则提取整数归一化到 0-1。解析失败或调用异常返回 0.0兜底不阻断流程。inputs vs expectations 的选择大多数 scorer 对照expectations标准答案评分但素材溯源类 scorer 应使用inputs原始素材——检查生成文本中的信息是否在输入素材中有依据这是防幻觉的核心维度。inputs不可用时返回中性分如 0.5。3.5 元数据管理前端通过元数据 API 获取可用 scorer 列表含标签、描述、默认推荐组合动态渲染配置表单。新增 scorer 只需在注册表中添加前端自动感知无需修改页面代码。4. 提示词版本迭代4.1 任务生命周期任务状态机pending → running → completed/failed/cancelled。创建任务后先持久化再提交后台执行避免竞态对 GEPA 这类迭代式优化器取消时写标记文件触发优雅退出而非强行 kill 线程异常时完整捕获并持久化错误信息4.2 后台执行模式采用 Web 框架原生的后台任务机制如 FastAPI BackgroundTasks将同步的run_optimization_task提交到线程池。DB 操作通过临时事件循环完成MLflow 优化在纯同步上下文运行——避开 MLflow 内部的 asyncio 冲突。4.3 执行流程准备阶段从 DB 加载任务数据 → 构建 MLflow 标准 train_data每条含 inputs 和 expectations→ 解析 prompt URI → 创建 predict_fn、收集 scorers、创建 optimizer。优化阶段调用mlflow.genai.optimize_prompts()MLflow 内部循环为逐条生成 → 评分 → 分析 → 修改模板 → 重新生成直到收敛或达到上限。持久化阶段将 initial_score、final_score、optimized_prompt_version 写回 DB。4.4 predict_fn 的关键设计内部加载 Promptpredict_fn 内部调用load_prompt()加载模板而非使用外部传入的固定模板。这是 MLflow 优化器正常工作的前提——只有内部加载MLflow 才能追踪 Prompt 使用、在优化过程中修改模板、优化结束后自动注册新版本。容错LLM 调用失败返回错误字符串而非抛异常避免单次失败中断整个优化任务。同步客户端MLflow 以同步方式调用 predict_fn因此必须使用同步 HTTP 客户端。4.5 优化器选型优化器原理适用场景MetaPromptOptimizer反思模型分析评分结果直接生成改进后的 prompt语义层面改进措辞、约束、指令结构GepaPromptOptimizer遗传算法种群 → 交叉变异 → 评分 → 选择搜索空间大、需探索多种变体共同参数reflection_model格式openai:/model-name。GEPA 额外需要max_metric_calls控制计算量上限。4.6 集成适配的三个常见问题依赖最小化某些优化器内部依赖重量级包如 GEPA 依赖 litellm。可通过注册最小化 shim 到sys.modules替代完整包仅实现优化器实际调用的函数。自定义 API 端点MLflow 内部的 OpenAI provider 默认走官方 API。通过 monkey-patch provider 工厂函数注入自定义 base_url使评分和反思调用都走自己的端点。Windows 兼容MLflow 可能输出非 ASCII 字符如 emoji在 Windows 上需重配置 stdout/stderr 为 UTF-8 编码。4.7 并发任务日志隔离多任务并发时通过线程 ID → 任务 ID 映射 自定义日志过滤器确保每个任务的日志写入独立文件。stdout 捕获MLflow 的 print 输出通过 TeeWriter 同时写控制台和文件行缓冲确保实时写入。5. 按需自举 — 首个版本的自动创建Registry 初始为空但optimize_prompts需要已存在的 Prompt 作为起点。resolve_prompt_uri()设计为多层回退先尝试 alias 加载 → 再尝试指定版本 → 再搜索最大版本。全部失败且错误码为RESOURCE_DOES_NOT_EXIST时触发自举——从预定义的初始模板字典中取对应模板注册 v1然后继续。初始模板包含基本角色设定和任务描述使用 MLflow 标准占位符{{ input_text }}。模板质量不高也没关系——优化器会在后续迭代中改进。这个机制的价值在于自动化不需要手动为每个 prompt 做首次注册。6. 优化结果的消费优化后的 Prompt 在生产使用时从 Registry 加载指定版本默认最新作为 system_prompt。关键实践是在生成结果中携带使用的 Prompt 版本号——实现从生成内容到 Prompt 版本的可追溯性。生成时建议带重试机制空响应或过短输出触发重试避免偶发网络抖动或模型异常导致生成中断。7. 涉及的框架配置整个提示词工程体系主要涉及两个框架的配置接口MLflowmlflow.set_tracking_uri()—— 设置 Tracking Server 地址这是 MLflow 的入口配置。优化器和 Registry 必须使用同一 URI 才能协同工作。Worker 线程中可覆盖为本地文件存储file:///.../mlruns避免分布式环境下的网络延迟和一致性问题优化器构造参数 ——reflection_model格式openai:/model-name指定优化器用于反思的模型、max_metric_callsGEPA 的最大评分调用次数作为早停条件、run_dirGEPA FileStopper 的工作目录用于优雅中断OpenAI 兼容客户端predict_fn 和 LLM Judge 共用同一套 OpenAI 兼容参数base_url、api_key、model、max_tokens、temperature。需要注意 predict_fn 和 LLM Judge 对参数的要求不同——Judge 侧应强制temperature0.0并限制max_tokens仅够返回分数与生成侧的参数分离。8. 关键技术决策决策选择理由版本管理后端MLflow Prompt Registry与优化器原生集成优化结果自动注册无需手动同步Scorer 注册方式mlflow_scorer装饰器声明式注册、按名发现新增 scorer 前端自动感知predict_fn 加载 Prompt内部load_prompt()MLflow 优化器追踪和修改模板的前提条件评估器分类规则型 LLM Judge 型规则型零成本高确定性Judge 型处理语义维度按场景配比LLM Judge temperature0.0消除评分随机性确保同一样本评分一致初始 Prompt按需自举自动化首次注册减少手动操作模板可审计优化器MetaPrompt GEPA 双选覆盖语义改进和探索搜索两种范式外部依赖最小化 shim仅实现被调用的函数避免完整包的依赖冲突并发模型框架原生 BackgroundTasks无需引入 Celery/ARQ 等重量级任务队列日志隔离线程过滤器 行缓冲并发任务的日志独立文件、实时可查