使用 Semantic Kernel Python 在 Azure AI Studio 上跑通 MMLU 多模型基准评测
【免费下载链接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps项目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel
本文以 python/samples/concepts/model_as_a_service 目录下的官方示例为主线,讲解如何用 Semantic Kernel Python 对 Llama3-8b、Phi3-mini、Phi3-small 等多个 Azure AI Studio 无服务器(Serverless/Model-as-a-Service)模型批量评测经典的MMLU(Massive Multitask Language Understanding)数据集,并输出每个模型的准确率。读完本文,你将掌握:MMLU 数据集的加载与学科裁剪、多 AI 服务注册与统一评测框架、零样本 prompt 的调优思路,以及把该脚本改造为自定义数据集基准测试的完整方法。
示例背景与设计意图
MMLU 是一个被广泛用于衡量大语言模型多任务理解能力的基准数据集,包含数十个学科的多选题。官方示例 mmlu_model_eval.py 用它来做两件有意义的事:
- 评估在 Azure AI Studio 上部署的 Model-as-a-Service(MaaS)模型,比如 Phi 系列、Llama 系列、Mistral large 等通过无服务器 API 提供的模型;
- 给开发者提供一个可扩展的基准测试脚手架——无论你是想新增一个数据集、扩展现有数据集来评测新模型,还是想复现学术论文中的评测结果,都可以以此脚本为起点。
仓库只读,本文只讲解查看、安装、运行与配置方法,不会改动仓库内容。
脚本默认挑选了三个模型作为对比基线:Llama3-8b、Phi3-mini、Phi3-small。选择依据来自论文Phi-3 Technical Report: A Highly Capable Language Model Locally on Your Phone(arxiv 2404.14219)第 6 页报告的评测结果:理论上 Phi3-small 优于 Phi3-mini,Phi3-mini 优于 Llama3-8b。跑完本示例你应能看到相同的相对排名——但绝对数值不会一致,因为论文报告使用的是 5-shot 评测,而本示例刻意采用zero-shot(零样本)评测,其目的正是留出空间让你通过调整 prompt 去逼近论文中的准确率。
前置准备:模型部署与依赖安装
运行该示例需要满足以下条件:
- 部署所需模型:在 Azure AI Studio 中把想评测的模型(如 Llama3-8b、Phi3-mini、Phi3-small)以无服务器 API 的形式部署,并拿到对应的 API key 与 endpoint。模型可用性以 Azure AI Studio 的模型目录为准。
- 准备 HuggingFace 访问令牌:MMLU 数据集托管在 HuggingFace 上(
cais/mmlu),访问需要 token。脚本运行时load_mmlu_dataset会调用login()提示你登录,你可以提前用huggingface-cli login配置好凭证。 - 安装依赖:在 Semantic Kernel Python 项目的虚拟环境中安装 HuggingFace
datasets模块:pip install datasets - 填写密钥与端点:把 API key 和 endpoint 填入脚本中
setup_kernel()对应的服务构造参数里。
完成上述步骤后,在激活了虚拟环境的终端中直接运行:
python mmlu_model_eval.py如果你使用 VS Code,也可以直接在虚拟环境解释器下选中脚本文件、点击文件面板右上角的运行图标来执行。
数据集加载:按学科裁剪 MMLU
MMLU 数据集包含众多按学科划分的子集,示例默认加载 5 个学科,你也可以在 mmlu_model_eval.py 的main()中按需增删:
datasets = load_mmlu_dataset([ "college_computer_science", "astronomy", "college_biology", "college_chemistry", "elementary_mathematics", # Add more subjects here. # See here for a full list of subjects: https://huggingface.co/datasets/cais/mmlu/viewer ])底层加载逻辑位于load_mmlu_dataset函数(mmlu_model_eval.py):
def load_mmlu_dataset(subjects: list[str]) -> dict[str, Dataset]: login() datasets = {} number_of_samples = 0 for subject in subjects: ds: DatasetDict = load_dataset("cais/mmlu", name=subject) validation_ds: Dataset = ds["validation"] datasets[subject] = validation_ds print(f"Loaded MMLU validation dataset for {subject}. This dataset has {validation_ds.num_rows} examples.") number_of_samples += validation_ds.num_rows print(f"Loaded {len(subjects)} datasets with a total of {number_of_samples} examples.") return datasets几个值得注意的实现细节:
- 它加载的是每个学科的validation(验证)分割,而非训练或测试分割;
- 返回结构是
dict[str, Dataset],以学科名为 key、对应验证集为 value,便于后续按学科逐条评测与统计; login()保证 HuggingFace 凭证可用,数据集通过datasets库的load_dataset按需拉取。
多模型注册:一个 Kernel 承载多个 AI 服务
评测的核心思想是让同一个评测框架自动遍历 Kernel 中注册的所有服务。setup_kernel()(mmlu_model_eval.py)为每个模型调用一次kernel.add_service注册AzureAIInferenceChatCompletion:
def setup_kernel(): """Set up the kernel with AI services.""" kernel = Kernel() # Add multiple AI services to the kernel kernel.add_service( AzureAIInferenceChatCompletion( ai_model_id="Llama3-8b", api_key="", endpoint="", ) ) kernel.add_service( AzureAIInferenceChatCompletion( ai_model_id="Phi3-mini", api_key="", endpoint="", ) ) kernel.add_service( AzureAIInferenceChatCompletion( ai_model_id="Phi3-small", api_key="", endpoint="", ) ) # Add the plugin to the kernel kernel.add_plugin(MMLUPlugin(), "MMLUPlugin") return kernel新增模型的扩展方式非常直接:复制一个add_service块、填入新的ai_model_id/api_key/endpoint即可,新服务会被自动纳入评测范围——因为main()通过kernel.get_services_by_type(ChatCompletionClientBase)动态枚举所有聊天补全服务(见 kernel_services_extension.py):
ai_services = kernel.get_services_by_type(ChatCompletionClientBase).keys()从源码看(azure_ai_inference_chat_completion.py),AzureAIInferenceChatCompletion的构造参数与默认行为如下:
| 参数 | 是否必填 | 说明 |
|---|---|---|
ai_model_id | 必填 | 用于标识模型的字符串,如模型名,也是评测结果输出中显示的名称 |
api_key | 可选 | Azure AI Inference 服务部署的 API key;缺省时从环境变量AZURE_AI_INFERENCE_API_KEY读取 |
endpoint | 可选 | Azure AI Inference 服务部署的 endpoint;缺省时从环境变量AZURE_AI_INFERENCE_ENDPOINT读取 |
api_version | 可选 | API 版本,缺省时读AZURE_AI_INFERENCE_API_VERSION |
service_id | 可选 | 服务的唯一 ID,不传时默认取ai_model_id的值 |
client | 可选 | 直接传入现成的ChatCompletionsClient实例 |
instruction_role | 可选 | 将 system 消息改写为developer角色(用于 summarization 等场景) |
关于 service_id 有一点值得注意:脚本中并未显式传service_id,这意味着服务 ID 默认等于ai_model_id。因此评测输出中的Llama3-8b、Phi3-mini等名称,既是模型标识也是注册到 Kernel 的服务 ID,二者在此处保持一致。同时 add_service 在service_id重复时会抛出异常(除非设置overwrite=True),这也提醒我们服务 ID 需要全局唯一。
评测插件:单样本问答与判分逻辑
MMLUPlugin是一个典型的 Semantic Kernel 原生插件(mmlu_model_eval.py),它通过@kernel_function装饰器暴露evaluate函数:接收一条样本与学科名,让指定服务作答并返回是否答对。
@kernel_function(name="evaluate", description="Run a sample and return if the answer was correct.") async def evaluate( self, sample: Annotated[dict, "The sample"], subject: Annotated[str, "The subject of the sample"], kernel: Annotated[Kernel, "The kernel"], service_id: Annotated[str, "The service id"], ) -> Annotated[bool, "Whether the answer was correct"]: # Initialize chat history with a system message chat_history = ChatHistory(system_message=formatted_system_message(subject)) # Add the user message to the chat history chat_history.add_user_message( formatted_question( sample["question"], sample["choices"][0], sample["choices"][1], sample["choices"][2], sample["choices"][3], ), ) # Determine the correct answer correct_answer = expected_answer_to_letter(sample["answer"]) # Get the chat response from the AI service response = await kernel.get_service(service_id).get_chat_message_content( chat_history, settings=kernel.get_prompt_execution_settings_from_service_id(service_id), ) if not response: return False # Compare the AI response with the correct answer return response.content.strip() == correct_answer这段代码揭示了完整的单样本评测链路,也是理解整个示例的关键:
- 构造对话:用
ChatHistory放入系统消息与用户消息,消息内容由 helpers.py 中的模板生成; - 取服务:
kernel.get_service(service_id)按服务 ID 取出对应 AI 服务;kernel.get_prompt_execution_settings_from_service_id(service_id)则实例化该服务专属的PromptExecutionSettings(见 kernel_services_extension.py); - 推理与判分:调用
get_chat_message_content拿到回复,将回复文本去除首尾空白后与标准答案字母做精确匹配;请求失败(response为空)时直接判False。
值得注意:与常规的kernel.invoke函数调用链不同,这里把kernel和service_id直接作为参数传入函数体,在函数内部手动完成“取服务 → 构建设置 → 发起对话”,这种写法非常适合评测场景中对服务选择的显式控制。
Prompt 模板与零样本设计
helpers.py 集中定义了 prompt 模板与答案转换逻辑,是调优准确率的主要入口:
def formatted_system_message(subject: str): """Return a formatted system message.""" return f""" You are an expert in {subject}. You answer multiple choice questions on this topic. """ def formatted_question(question: str, answer_a: str, answer_b: str, answer_c: str, answer_d: str): """Return a formatted question.""" return f""" Question: {question} Which of the following answers is correct? A. {answer_a} B. {answer_b} C. {answer_c} D. {answer_d} State ONLY the letter corresponding to the correct answer without any additional text. """ def expected_answer_to_letter(answer: str): """Return the letter corresponding to the expected answer. The dataset contains numbers as answers, this function converts them to letters. """ return ["A", "B", "C", "D"][int(answer)]三个函数各司其职:
formatted_system_message(subject):把学科名注入系统消息,让模型扮演对应学科专家;formatted_question(...):把问题与四个选项组织成多选题格式,并强制要求只输出答案字母——这是保证判分稳定性的关键设计;expected_answer_to_letter(answer):MMLU 原始答案用数字 0~3 表示,这里映射为["A", "B", "C", "D"]对应下标,从而与模型输出的字母比较。
示例刻意采用 zero-shot(不提供任何示例),便于你在此基础上观察 prompt 工程对准确率的影响;想要逼近论文的 5-shot 结果,可以在这个文件中扩展 few-shot 的示例拼接逻辑。
主循环:逐学科、逐样本、逐模型批量评测
main()(mmlu_model_eval.py)将前面所有部件串成完整的评测流水线:
async def main(): datasets = load_mmlu_dataset([...]) kernel = setup_kernel() ai_services = kernel.get_services_by_type(ChatCompletionClientBase).keys() totals = sum([datasets[subject].num_rows for subject in datasets]) total_corrects = {ai_service: 0.0 for ai_service in ai_services} for subject in datasets: corrects = {ai_service: 0.0 for ai_service in ai_services} print(f"Evaluating {subject}...") for sample in tqdm(datasets[subject]): for ai_service in ai_services: kernel_arguments = KernelArguments( sample=sample, subject=subject, kernel=kernel, service_id=ai_service, ) result = await kernel.invoke( plugin_name="MMLUPlugin", function_name="evaluate", arguments=kernel_arguments ) if result.value is True: corrects[ai_service] += 1 print(f"Finished evaluating {subject}.") for ai_service in ai_services: total_corrects[ai_service] += corrects[ai_service] print(f"Accuracy of {ai_service}: {corrects[ai_service] / datasets[subject].num_rows * 100:.2f}%.") print("Overall results:") for ai_service in ai_services: print(f"Overall Accuracy of {ai_service}: {total_corrects[ai_service] / totals * 100:.2f}%.")流程可以归纳为三层循环:
- 外层按学科遍历:对每个学科先统计该学科内各服务的答对数量,输出单学科准确率;
- 中层按样本遍历:借助
tqdm显示进度条,逐条样本调用kernel.invoke(plugin_name="MMLUPlugin", function_name="evaluate"); - 内层按服务遍历:同一份样本依次喂给所有注册的聊天补全服务,
KernelArguments中的service_id让evaluate知道该用哪个模型作答。
最终,各学科准确率汇总后得到每个模型的总体准确率。这套“一个 Kernel、多个服务、统一插件”的模式,可以平滑迁移到你自己的数据集:只需替换load_mmlu_dataset的加载来源,并让样本 dict 提供question、choices、answer三个字段即可。
运行结果解读
示例运行结束后,会依次输出每个学科、每个模型的准确率,最后汇总总体结果,输出形如:
Finished evaluating college_biology. Accuracy of Llama3-8b: 75.00%. Accuracy of Phi3-mini: 81.25%. Accuracy of Phi3-small: 93.75%. ... Overall results: Overall Accuracy of Llama3-8b: 51.09%. Overall Accuracy of Phi3-mini: 55.43%. Overall Accuracy of Phi3-small: 66.30%.解读时注意三点:
- 相对排名比绝对值更可靠:由于是 zero-shot 且 prompt 模板不同,绝对数值不会与论文完全一致,但模型间的相对强弱应保持一致;
- 数值差异的根源:论文采用 5-shot、本示例采用 zero-shot,这是两者数值不同的主因,也是你调 prompt 的切入点;
- 可验证性:准确率的计算完全由
corrects[ai_service] / datasets[subject].num_rows与total_corrects[ai_service] / totals得出(见 mmlu_model_eval.py),结构透明,便于核对与二次开发。
扩展指南:如何评测自己的数据集
把该示例改造成自定义数据集基准测试时,只需关注三处:
- 数据源:把
load_mmlu_dataset中的load_dataset("cais/mmlu", name=subject)替换为你自己的数据集来源,并确保每条样本包含question、choices(长度为 4 的列表)、answer(0~3 的整数下标)字段;若字段名不同,同步修改MMLUPlugin.evaluate与formatted_question的取值逻辑; - 模型集合:在
setup_kernel()中按需增删AzureAIInferenceChatCompletion服务,只要是模型目录中可用的 MaaS 模型即可,新服务会被get_services_by_type(ChatCompletionClientBase)自动发现; - Prompt 策略:在 helpers.py 中调整系统消息与问题格式,甚至可以加入 few-shot 示例来复现学术论文中的评测设置。
整个示例充分体现了 Semantic Kernel Python 的“插件 + 函数 + 服务注册”组合能力:评测逻辑被封装为MMLUPlugin插件,多模型通过服务注册机制统一驱动,评测维度通过数据集裁剪灵活扩展——这套结构本身就是一份可直接复用的多模型基准评测模板。
【免费下载链接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps项目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考