MLflow 大语言模型实战:基于 prompt engineering 的文本摘要与问答示例全解析
【免费下载链接】mlflowThe open source AI engineering platform for agents, LLMs, and ML models. MLflow enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality AI applications while controlling costs and managing access to models and data.项目地址: https://gitcode.com/GitHub_Trending/ml/mlflow
本篇技术指南以当前仓库 examples/llms/README.md 为骨架,围绕 MLflow 在 LLM 场景下的两条完整实战链路展开:一条用 LangChain 构建新闻摘要模型,另一条用 OpenAI 原生接口构建 MLflow 问答机器人。两条链路都走通了「prompt engineering 建模 → flavor 打包记录 →mlflow.evaluate()自动评估 →mlflow.pyfunc.load_model()加载评分」的完整闭环。读完本文,你将能复现这两个示例,并理解mlflow.langchain与mlflow.openai两个 LLM flavor 的用法、text-summarization与question-answering两类评估任务的指标体系,以及如何用代码比较多个 prompt 的优劣并挑选最佳模型。
一、示例总览:examples/llms 目录结构
examples/llms目录是 MLflow 仓库中面向 LLM 使用场景的示例集合,核心结构如下:
examples/llms/ ├── README.md # 本文对应的官方说明 ├── summarization/ # 文本摘要示例(LangChain) │ ├── MLproject │ ├── python_env.yaml │ ├── summarization.py │ └── summarization_example_data.csv ├── question_answering/ # 问答示例(OpenAI) │ ├── MLproject │ ├── python_env.yaml │ └── question_answering.py └── RAG/ # 检索增强生成与检索器评估教程 ├── retriever-evaluation-tutorial.ipynb ├── question-generation-retrieval-evaluation.ipynb └── static_evaluation_dataset.csv其中summarization与question_answering是两个可直接运行的端到端示例,RAG目录则提供了检索器评估的 Notebook 教程与静态评估数据集,可作为进阶阅读材料。本文聚焦前两个可运行示例。
两个示例都遵循同一条方法论:用不同的 prompt 构建多个候选模型 → 分别记录进 MLflow → 用同一份小样本数据评估它们 → 从评估结果中挑选最优 prompt → 用该模型对新输入评分。这正是 prompt engineering 在 MLflow 中的标准落地姿势:prompt 本身作为可复现、可比较、可版本化的实验参数。
二、运行环境准备
两个示例均要求 MLflow2.4.0 及以上版本,且必须设置OPENAI_API_KEY环境变量。示例脚本会在启动时主动断言该变量是否存在,缺失时直接抛错(见 summarization.py 与 question_answering.py)。
2.1 摘要示例的依赖
summarization/python_env.yaml 完整声明了运行环境:
python: "3.10" build_dependencies: - pip dependencies: - langchain>=0.0.244 - openai>=0.27.2 - evaluate>=0.4.0 - mlflow>=2.4.0 - tiktoken>=0.4.0除上述声明外,官方说明还建议安装 Hugging Face 的evaluate库(已包含在 yaml 中)来计算ROUGE 指标(面向摘要质量的评估指标)。此外,从评估器底层实现看,若要完整计算 ROUGE,还需nltk与rouge_score;若评估器要计算 toxicity 指标,则还需要torch与transformers(详见下文「评估器的指标体系」一节)。
2.2 问答示例的依赖
question_answering/python_env.yaml 声明了另一组依赖:
python: "3.10" build_dependencies: - pip dependencies: - openai>=0.27.2 - tiktoken>=0.4.0 - tenacity>=8.2.2 - mlflow>=2.4.0其中tiktoken用于 token 计数,tenacity用于对 OpenAI API 调用做重试容错。
2.3 两种运行方式
每个示例都提供了两种等价的运行入口,官方推荐在对应子目录内执行:
方式一:以 MLflow Project 运行(自动解析 MLproject 与环境)
$ cd summarization && mlflow run .$ cd question_answering && mlflow run .方式二:直接以 Python 脚本运行
$ cd summarization && python summarization.py$ cd question_answering && python question_answering.py两种方式共用同一份MLproject定义。以摘要示例为例,summarization/MLproject 内容为:
name: llm_summarization python_env: python_env.yaml entry_points: main: command: python summarization.py问答示例的 question_answering/MLproject 结构相同,项目名为llm_question_answering。这解释了为什么mlflow run .能直接拉起脚本:MLflow 依据python_env字段重建环境,并执行entry_points.main.command。
三、示例一:基于 LangChain 的新闻摘要模型
3.1 核心代码拆解
summarization/summarization.py 的核心是build_and_evaluate_model_with_prompt(prompt_template)函数,它把「构建—记录—评估」三步封装在一个 run 内:
def build_and_evaluate_model_with_prompt(prompt_template): mlflow.start_run() mlflow.log_param("prompt_template", prompt_template) # 用 LangChain 构建新闻摘要模型并记录到 MLflow Tracking llm = OpenAI(temperature=0.9) prompt = PromptTemplate(input_variables=["article"], template=prompt_template) chain = LLMChain(llm=llm, prompt=prompt) logged_model = mlflow.langchain.log_model(chain, name="model") # 在小样本数据集上评估模型 sample_data = pd.read_csv("summarization_example_data.csv") mlflow.evaluate( model=logged_model.model_uri, model_type="text-summarization", data=sample_data, targets="highlights", ) mlflow.end_run()关键点逐条展开:
mlflow.log_param("prompt_template", prompt_template):把 prompt 模板本身作为参数记录。由于两个候选模型只有 prompt 不同,这个参数就成了对比实验的分组键,后续可直接从评估结果表里按params.prompt_template分组对比。OpenAI(temperature=0.9):创建一个 temperature 较高的 OpenAI LLM,给予生成摘要更多随机性与多样性;PromptTemplate(input_variables=["article"], template=...)声明模板的输入变量为article。mlflow.langchain.log_model(chain, name="model"):使用mlflow.langchainflavor将整个LLMChain打包记录。这是 MLflow 支持 LangChain 模型的标准方式,chain会被序列化为 MLflow 模型,返回的logged_model.model_uri可直接作为mlflow.evaluate()的model参数。mlflow.evaluate(...):以model_type="text-summarization"在 CSV 样例数据上自动评估,targets="highlights"指明数据集中作为参考答案的列名。
3.2 两个候选 prompt 的设计对比
脚本构造了两个 prompt,分别构建、评估一轮:
prompt_template_1 = ( "Write a summary of the following article that is between triple backticks: ```{article}```" ) prompt_template_2 = ( "Write a summary of the following article that is between triple backticks. Be concise. Make" " sure the summary includes important nouns and dates and keywords in the original text." " Just return the summary. Do not include any text other than the summary: ```{article}```" )第一个 prompt 只做最朴素的指令;第二个则追加了「简洁」「保留重要名词、日期与关键词」「只返回摘要正文」等约束。二者刻意拉开指令精细度的差距——这正是为了在评估环节直观展示 prompt 质量对生成结果的影响。
3.3 评估数据格式
评估所用样例数据 summarization_example_data.csv 为三列格式:id(样本唯一标识)、article(新闻原文)、highlights(人工撰写的摘要,作为targets参考答案)。CSV 中共有 5 条新闻样本,覆盖体育、航天、消费等领域。id列对应了评估器输出中 per-row 结果的标识,这也是后续按样本聚合结果时用id排序的原因。
3.4 加载评估结果并对比 prompt
两轮构建与评估结束后,脚本用mlflow.load_table()把每次评估落盘的eval_results_table.json汇总加载,并额外带上 run 级参数列:
results: pd.DataFrame = mlflow.load_table( "eval_results_table.json", extra_columns=["run_id", "params.prompt_template"] ) results_grouped_by_article = results.sort_values(by="id") print("Evaluation results:") print(results_grouped_by_article[["run_id", "params.prompt_template", "article", "outputs"]])mlflow.load_table()是 MLflow 提供的便利 API:它会自动扫描当前实验下各 run 的 artifacts 中名为eval_results_table.json的文件,合并成一张 DataFrame,并通过extra_columns把run_id、params.prompt_template等 run 元数据作为列拼接到结果表上。这样每次评估的原始输出(outputs)与所用 prompt 一一对应,可以直接在终端里对比哪个 prompt 生成的摘要质量更高。
3.5 加载最佳模型并评分新文章
脚本默认把 prompt 2 视为更优的候选(更精细的指令),用runs:/<run_id>/model这个 MLflowrun 相对模型 URI加载并评分:
best_model = mlflow.pyfunc.load_model(f"runs:/{mlflow.last_active_run().info.run_id}/model") summary = best_model.predict({"article": new_article}) print(f"Summary: {summary}")runs:/<run_id>/model是 MLflow 模型注册表之外的轻量寻址方式:<run_id>是某次 run 的 ID,model是该 run 下以name="model"记录的模型工件路径。mlflow.pyfunc.load_model()返回统一的 Python Function 模型封装,无论底层是 LangChain、OpenAI 还是其他 flavor,都通过predict()进行推理,输入格式与模型记录的输入 schema 对齐——摘要模型接收形如{"article": new_article}的 dict。
new_article是一段关于曼联球员 Januzaj 现身斯诺克世锦赛的英文新闻(约 100 词),脚本会打印出模型生成的摘要。至此,「构建 → 记录 → 评估 → 对比 → 加载 → 评分」的完整闭环跑通。
四、示例二:基于 OpenAI 的 MLflow 问答模型
4.1 核心代码拆解
question_answering/question_answering.py 的思路与摘要示例一致,但模型构建方式换成了mlflow.openaiflavor:
def build_and_evaluate_model_with_prompt(system_prompt): mlflow.start_run() mlflow.log_param("system_prompt", system_prompt) # 用 OpenAI 原生接口构建问答模型并记录到 MLflow Tracking logged_model = mlflow.openai.log_model( model="gpt-4o-mini", task=openai.chat.completions, name="model", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": "{question}"}, ], ) # 在若干示例问题上评估模型 questions = pd.DataFrame({ "question": [ "How do you create a run with MLflow?", "How do you log a model with MLflow?", "What is the capital of France?", ] }) mlflow.evaluate( model=logged_model.model_uri, model_type="question-answering", data=questions, ) mlflow.end_run()关键参数说明:
model="gpt-4o-mini":指定使用的 OpenAI 模型 ID,这是当前仓库代码中实际使用的值(注意与早期文档中的gpt-4o不同,请以仓库实际内容为准)。OpenAI 侧模型的可用性与计费由其服务端决定。task=openai.chat.completions:声明任务类型为 Chat Completions,mlflow.openaiflavor 会据此将模型解析为对话式请求。messages=[...]:定义消息模板。{question}是占位符,在推理阶段会被真实问题替换;system_prompt参数则动态注入每个候选模型的 system 消息。mlflow.evaluate(..., model_type="question-answering"):注意此例没有传targets——与摘要示例不同,问答评估的参考答案是可选项,无参考答案时评估器只计算不需要 ground truth 的指标(见下文)。- 三个示例问题中刻意混入了一个与 MLflow 无关的问题("What is the capital of France?"),用于检验 system prompt 是否具备「拒答无关问题」的能力——这是 prompt 2 的核心设计意图。
4.2 两个候选 system prompt 的设计对比
system_prompt_1 = "Your job is to answer questions about MLflow." system_prompt_2 = ( "Your job is to answer questions about MLflow. When you are asked a question about MLflow," " respond to it. Make sure to include code examples. If the question is not related to" " MLflow, refuse to answer and say that the question is unrelated." )prompt 1 仅声明职责;prompt 2 进一步约束了回答要包含代码示例,并明确要求对与 MLflow 无关的问题拒绝回答。通过对比两个 prompt 在「法国首都」这类无关问题上的输出,就能直观看出约束指令是否生效。
4.3 加载结果与评分新问题
与摘要示例对称,脚本用mlflow.load_table("eval_results_table.json", extra_columns=["run_id", "params.system_prompt"])汇总两次评估,按question排序后打印run_id、params.system_prompt、question、outputs四列;随后用mlflow.pyfunc.load_model(f"runs:/{mlflow.last_active_run().info.run_id}/model")加载最后一个 run 对应的模型(prompt 2),对一个关于 Model Registry 的新问题做预测:
new_question = "How do you create a model version with the MLflow Model Registry?" best_model = mlflow.pyfunc.load_model(f"runs:/{mlflow.last_active_run().info.run_id}/model") response = best_model.predict(new_question) print(f"Response: {response}")注意问答模型的predict()输入是单个问题字符串(new_question)而非 dict,这是与摘要模型在输入契约上的差异,源于mlflow.openai记录时输入占位符{question}的定义方式。
五、评估器底层原理:两类 LLM 评估任务的指标体系
两个示例中的model_type参数最终都会路由到 MLflow 的默认评估器。在 mlflow/models/evaluation/base.py 中可以看到这两个评估任务类型的正式定义:
QUESTION_ANSWERING = "question-answering" TEXT_SUMMARIZATION = "text-summarization"根据 evaluate() 的文档说明,默认评估器对这两类任务的产出如下:
question-answering(问答)任务:
- 指标:
exact_match(精确匹配)、token_count(token 数)、toxicity(毒性检测,需安装evaluate与torch)、flesch_kincaid_grade_level与ari_grade_level(可读性等级,需安装textstat)。 - 工件:一份 JSON 文件,以表格形式记录模型的输入、输出、
targets(若提供)以及逐行指标。
text-summarization(文本摘要)任务:
- 指标:
token_count、ROUGE(需安装evaluate、nltk、rouge_score)、toxicity(需evaluate、torch、transformers)、ari_grade_level与flesch_kincaid_grade_level(需textstat)。 - 工件:同样是一份包含输入/输出/targets/逐行指标的 JSON 表格文件。
两个关键事实可以由此确认:
targets是可选参数:文档明确指出 targets 对 question-answering、text-summarization、text 三类模型可选。这正是问答示例不传targets也能正常运行的原因;而摘要示例传了targets="highlights",于是评估器能够计算 ROUGE 等需要参考答案的指标。- 指标按需加载依赖:ROUGE、toxicity、可读性等指标有各自的第三方依赖。若环境中缺少对应依赖,相关指标会被跳过或告警,其余指标不受影响。这也解释了 summarization/python_env.yaml 中显式声明
evaluate>=0.4.0的用意——它是 ROUGE 计算的前置依赖。
六、进阶阅读:RAG 检索评估教程
除两个可运行示例外,examples/llms/RAG目录提供了面向检索增强生成场景的扩展内容,与本文主题一脉相承:
- retriever-evaluation-tutorial.ipynb:检索器评估教程,演示如何用静态数据集量化评估检索器质量。
- question-generation-retrieval-evaluation.ipynb:问题生成 + 检索 + 评估的完整流程。
- static_evaluation_dataset.csv 与 mlflow_docs_scraped.csv:教程配套的静态评估数据与 MLflow 文档抓取语料。
- faiss_index:教程配套的 FAISS 向量索引工件。
这部分内容适合在跑通基础示例后,进一步探索「检索 + 生成」组合下的 LLM 应用评估。
七、总结与关键经验
| 维度 | Summarization 示例 | Question Answering 示例 |
|---|---|---|
| 模型构建方式 | mlflow.langchain.log_model(LLMChain) | mlflow.openai.log_model(...) |
| 记录的核心参数 | prompt_template | system_prompt |
| 评估任务类型 | text-summarization | question-answering |
是否传targets | 是(highlights列) | 否(可选) |
| 核心评估指标 | ROUGE、token_count 等 | exact_match、token_count 等 |
| 评分输入契约 | {"article": str} | str |
从这两个示例可以沉淀出可复用的工程范式:
- prompt 即实验变量:把 prompt 模板通过
mlflow.log_param()记录,让每次 prompt 迭代都变成可回溯、可对比的 run。 - flavor 决定打包方式:LangChain 链用
mlflow.langchain,原生 OpenAI 调用用mlflow.openai,二者最终都统一为可通过mlflow.pyfunc.load_model()+predict()调用的标准模型。 - 评估自动化:
mlflow.evaluate()根据model_type自动选择指标集与工件产出,无需手写评估脚本;mlflow.load_table("eval_results_table.json")则把多次实验的逐行结果汇总成表,方便横向对比。 - 部署寻址简单:
runs:/<run_id>/model提供了不依赖模型注册表的轻量加载路径,适合快速验证;生产环境可进一步将其注册到 Model Registry 做版本管理。
本文所涉代码均可直接在仓库的 examples/llms/summarization 与 examples/llms/question_answering 目录中查看、运行与修改,作为你自己 LLM 应用落地的起点。
【免费下载链接】mlflowThe open source AI engineering platform for agents, LLMs, and ML models. MLflow enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality AI applications while controlling costs and managing access to models and data.项目地址: https://gitcode.com/GitHub_Trending/ml/mlflow
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考