在快速演进的 artificial intelligence 领域中,为你的 use case 选择合适模型,既是一门艺术,也是一门科学。Microsoft Foundry 提供了一个庞大的 model catalog,截至 2026 年初,包含来自 OpenAI、Meta、Mistral AI、Cohere 等领先 providers 的 1,800 多个 pre-trained models。本章将探索如何浏览这个庞大生态,如何有效评估 models,并针对你的具体 business requirements 对其进行优化。
在第 2 章中,你已经创建了第一个 Microsoft Foundry project 并部署了一个 model。本章将在这一基础上,进一步深入 model selection process。你将学习如何基于 performance criteria 评估 models,应用 advanced prompt engineering techniques,使用 industry-standard datasets 评估 models,并 fine-tune models 以获得最佳结果。
本章将覆盖以下主题:
- Overview of the Microsoft Foundry Model Catalog
- Key criteria for Model Selection
- Advanced prompt engineering and context Engineering
- Evaluating Models with open-source datasets
- Fine-Tuning and Customization
- Case Studies
Technical requirements
要跟随本章中的代码示例,你需要具备以下条件:
- 一个 active Azure subscription,并且已经创建 Microsoft Foundry project resource。设置方法请参见第 2 章。
- 本地安装 Python 3.10 或更高版本,并安装 Microsoft Foundry Python SDK 及相关支持库:
pip install azure-ai-projects azure-ai-agents azure-identity
pip install openai python-dotenv scikit-learn numpy
- 在你的 Foundry project 中至少部署一个 model,推荐 GPT-4o;如果你的 region 可用,也可以使用 GPT-4.1 或更高版本,因为 model availability 会因 deployment date 而变化。
- 访问 Microsoft Foundry portal:
https://ai.azure.com,用于可视化探索 Model Catalog。
Overview of the model catalog
Microsoft Foundry Model Catalog 是你访问 state-of-the-art AI models 的入口。不同于传统 model marketplaces,Microsoft Foundry 将这些 models 直接集成进你的 development workflow,并提供 enterprise-grade security、compliance 和 responsible AI controls。
在本节中,我们将首先探索 Model Catalog 的 architecture,以及它所包含的主要 model categories。随后,我们将逐步介绍如何通过 Microsoft Foundry portal 和 Microsoft Foundry SDK 访问 catalog,以及如何根据 workload characteristics 在两种主要 deployment modes,也就是 serverless API 和 managed compute 之间做选择。最后,我们将覆盖 model versioning,使你能够采用新的 model releases,而不会破坏 downstream consumers。
Model catalog architecture
当你打开 Model Catalog 时,会看到数十个 models 被分为四个大类。理解每个 category 的优化目标非常重要,因为 category 选择往往比在同一 category 内比较单个 models 更能缩小选择范围。请将下面这些 categories 视为一个 decision funnel:先识别哪一类最匹配你的任务,再深入比较具体 models。
Model Catalog 被组织为几个关键 categories:
Foundation models:GPT-4、GPT-4o 和 Claude 等 large language models(LLMs),擅长 general-purpose text generation、reasoning 和 conversation。
Open-source models:来自 Meta,例如 Llama 3.1、Llama 3.2;Mistral AI,例如 Mistral Large、Mistral Small;以及其他社区驱动的 models,提供 flexibility 和 customization。
Specialized models:面向特定领域的 models,包括 vision,例如 GPT-4 Vision、Florence;speech,例如 Whisper;embeddings,例如 text-embedding-ada-002;以及 multimodal tasks。
Fine-tuned variants:base models 的预 fine-tuned 版本,针对 code generation、summarization 或 instruction following 等特定任务优化。
Model Catalog 会持续更新。写作时,catalog 大约包含 1,800–1,900 个 models,截至 2026 年初;随着新 models 和 versions 被加入,这个数量会定期增长。
实践中,大多数生产决策通常涉及选择一个 foundation model 来覆盖广泛能力和 reasoning,一个 specialized model 来处理窄模态任务,例如 vision、speech 或 embeddings,以及可能选择一个 fine-tuned variant 来服务 domain-specific workflow。本章其余部分默认采用这个思维模型:你首先判断 use case 属于哪个 category,然后使用下一节中的 evaluation framework,在该 category 内比较候选 models。
Accessing the model catalog
你可以通过 Microsoft Foundry portal 和 Microsoft Foundry SDK 两种方式访问 Model Catalog。Portal 是交互式浏览、比较和评估 models 的最快方式,因此非常适合 initial exploration 和 model selection。SDK 则是你在 production code 中使用的路径,它可以与 CI/CD pipelines、Infrastructure as Code workflows 和 programmatic deployment automation 干净集成。大多数 teams 会同时使用两者:portal 用于 discovery,SDK 用于真正上线的内容。
Gaining portal access
要通过 portal 访问 Model Catalog,可以按照以下步骤操作:
- 进入你在第 2 章中创建的 Microsoft Foundry project。
- 从左侧导航栏中选择 Model catalog。
- 按 category、provider 或 use case 浏览 models。
- 使用 filters 按 capability 缩小范围,例如 chat、embeddings、vision。
图 4.1:Model Catalog portal with deployment-mode filters applied
Gaining SDK access
要通过 SDK 访问 Model Catalog,可以使用下面的代码块:
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
# Initialize project client
credential = DefaultAzureCredential()
project = AIProjectClient(
endpoint="https://<your-project-endpoint>.cognitiveservices.azure.com",
credential=credential
)
配置好 Foundry project client 后,benchmark 的核心是一个函数:它会提交每个 test prompt,测量 end-to-end latency,并捕获 API 返回的 token counts。我们使用 time.time() 包围 complete() 调用来测量 wall-clock latency,因为这才是 production users 实际感受到的延迟。
# List available models
models = project.models.list()
for model in models:
print(f"Model: {model.name}, Provider: {model.publisher}, Task: {model.task}")
这段代码会连接到你的 Microsoft Foundry project,并获取可用 models 的完整列表及其 metadata。
Deployment options
当你想选择一个 model 时,应该花时间了解该 model 以及它支持的 deployment 类型。例如,如果你选择 gpt-4o 作为 model,并计划将它用于 production,可以将 deployment 命名为 "gpt-4o-production"。这样可以帮助你在 deployment 时更清楚这个 model 的用途。
选择 model 后,Microsoft Foundry 提供两种主要 deployment modes,使你可以部署 model 并开始运行 inference。这两种模式如下。
Serverless API deployment
这种模式会将每个 model 暴露在一个 pay-as-you-go 的 Microsoft-hosted endpoint 后面。你可以像调用其他 REST API 一样调用它;Microsoft 会代你管理 compute、scaling 和 availability SLA。你不需要 provision VM、选择 SKU 或调整 cluster size,只需要部署 model 并发起 requests。
这种模式具有以下优点:
- 基于 processed tokens 的 pay-per-use pricing。
- 不需要 infrastructure management。
- 适合 development、testing 和 variable workloads。
- 基于 demand 自动 scaling。
举一个具体例子:某 healthcare provider 的 pilot program 正在测试 clinical summarization agent,每天大约处理 200 到 500 个 requests。流量在 morning rounds 期间突增,而夜间几乎为零。这里 serverless 是正确选择,因为 team 只需为消耗的 tokens 付费;如果采用按 peak load 配置的 managed compute deployment,它一天大部分时间都会闲置,却仍持续计费。
Managed Compute Deployment
这种模式会将 model 部署到你预先配置和预留的 dedicated VM instances 上。你需要选择 SKU、instance count 和 region,agent runtime 会在这些 reserved resources 上运行 inference。由于不再与其他 tenants 共享 infrastructure,你可以获得 predictable latency 和 throughput,并且可以挂载 custom networking 或 private endpoints,以满足 data residency requirements。
这种模式具有以下优点:
- Dedicated compute resources,也就是 VM instances。
- Predictable performance 和 latency。
- 更适合 high-throughput production workloads。
- 对 model configuration 有更多控制。
一个代表性例子是区域性 healthcare system 的 patient-facing triage chatbot,它在 business hours 中持续处理 50 到 100 requests per second,并且必须满足 p99 latency 低于 2 秒的 SLA。Managed compute 在这里更合理,因为 provisioned capacity 提供 predictable performance,instances 可以锁定到 HIPAA-compliant region,并且在这种 request volume 下,有效 per-token cost 通常比 serverless pricing 低 30% 到 50%。
在 portal 中,你可以根据 deployment options 选择 models。下图展示了如何基于 deployment options 筛选 models。
图 4.2:Filtering models by managed compute deployment type in the Model Catalog
请特别注意 catalog 顶部的 filter chips。“Deployment options” facet 可以让你将结果缩小到支持 serverless API deployment、managed compute deployment 或二者都支持的 models。每个 model 的 collection card header 会显示 deployment-mode badge,鼠标悬停在 badge 上可以看到支持的 SKUs 和 regions。
在为 production 评估候选 model 时,应在筛选阶段尽早使用这个 facet:如果某个 model 只支持一种 deployment mode,而你的 workload 要求另一种,那么无论它的 evaluation scores 多好,它都不应继续被考虑。
Model versioning and updates
Catalog 中的 models 都有版本,以确保 reproducibility,并支持 seamless updates。
下面的代码片段展示了如何通过 SDK 部署特定 model version,并在向它发送 inference traffic 前验证 deployment。关键参数是 model_id,用于识别 model family;以及 model_version,用于固定具体 revision。明确 pinning version 对 reproducibility 非常重要:如果不这样做,Azure 会默认使用最新 stable release,这意味着当 Microsoft 发布新版本时,你的 production behavior 可能静默变化。
# Deploy a specific model version
deployment = project.deployments.create(
model_id="gpt-4o",
version="2024-11-20",
deployment_name="gpt-4o-production",
deployment_type="serverless"
)
# List all versions of a model
versions = project.models.get_versions("gpt-4o")
for version in versions:
print(f"Version: {version.version}, Released: {version.release_date}")
请始终记住:在 production environments 中,务必 pin specific model versions,以确保 behavior 一致。New versions 可能引入 response format、reasoning patterns 或 performance characteristics 的变化。
选择正确 model 很少是一次性决策,而是一个 iterative process。它从 task requirements 开始,然后通过一系列实际 trade-offs 推进,包括 quality、cost、latency、context size 和 deployment mode。下一节将把这些 trade-offs 作为一个 framework 展开,帮助你直接应用到自己的 use case 中,并贯穿 healthcare-focused examples。
Criteria for model selection
在以下小节中,我们将考察 task alignment、performance metrics、context considerations 和 cost strategies,作为逐步缩小 model choices 的 framework。选择正确 model 需要平衡多个因素,包括 task requirements、performance needs、cost constraints 和 latency expectations。
你会遇到一些术语,例如 Azure Direct Models,它们是经过严格筛选、推荐给 customer GenAI scenarios 的最相关 models。还有其他 models 则适合 general-purpose language tasks,包括 reasoning、knowledge、QA、mathematical reasoning 和 coding capabilities。本节提供一个结构化的 model evaluation framework。
图 4.3:Model selection decision framework
Task alignment
Model selection 的第一步,是理解你的 task requirements。基于需求,你可以在更高层级上分类自己要找的内容,然后为任务选择理想 model。
如下图所示,你可以浏览 leaderboards,查看哪些 model 在 Quality、Safety、Cost 和 Throughput 四个 pillars 上表现突出。
图 4.4:Model leaderboard comparison for quality, safety, cost, and throughput
下面看一些常见 tasks,以及你可能会选择哪些 models 来完成这些任务。
Text Generation and Conversation
GPT-4、GPT-4o:最适合 complex reasoning、creative writing 和 multi-turn conversations。
GPT-4o-mini:适合 straightforward Q&A 和 simple generation tasks,成本更低。
Llama 3.1 70B:具备强 general capabilities 的 open-source alternative。
Code Generation
GPT-4o:对 code context 和 debugging 有更强理解。
Codex / GPT-4o-mini:专门用于 code completion。
Code Llama:具备强 coding performance 的 open-source option。
Embeddings and Semantic Search
text-embedding-ada-002:高质量、成本有效的 embeddings。
text-embedding-3-small / large:新一代 embedding models,性能更好。
Cohere Embed:针对 multilingual use cases 优化。
Vision and Multimodal
GPT-4 Vision:最适合复杂 image understanding 和 reasoning。
GPT-4o:集成 vision 和 text processing。
Florence:Microsoft 的 specialized vision model,用于 classification 和 detection。
Performance metrics
当你已经识别任务并筛选出几个 candidate models 后,下一步是选择正确的 evaluation metrics。Foundry 可以帮助你基于这些关键 performance dimensions 评估 models。一些关键 metrics categories 如下:
Quality Metrics
Accuracy:对 factual questions 回答的正确性。
Coherence:生成文本中的 logical flow 和 consistency。
Relevance:与 user intent 和 context 的对齐程度。
Creativity:生成 novel、appropriate responses 的能力。
Efficiency Metrics
Latency:Time to first token(TTFT)和 overall response time。
Throughput:每秒处理的 requests 数量。
Token Efficiency:相对于 token consumption 的 output quality。
Cost per Request:包括 input 和 output tokens 在内的 total cost。
另一种评估 model performance 的方法是 benchmark comparisons。在 Foundry portal 中,进入 Model Catalog > select a model > Benchmarks tab。当你进入某个具体 model 的 Benchmarks tab 时,可以获取大量信息来更好理解和解释 benchmark results,包括:
图 4.5:Model card detail view in Foundry — the Overview tab showing model description, capabilities, context window, supported regions, and the Deploy button
High-level aggregate scores:针对 AI quality、cost、latency 和 throughput 的专门分数。
Comparative charts:展示 models 与其他相关 models 的相对位置。
Metric comparison:该表展示每个 metric 的详细结果。
通常,当你需要在 standard tasks,例如 text generation、Q&A、code generation、summarization 上快速对 shortlist candidate models 做 side-by-side comparison 时,可以依赖 Foundry 的 built-in benchmark scores。当你的 use case 有 domain-specific correctness criteria,而 off-the-shelf benchmarks 无法捕捉这些标准时,则应使用 custom evaluation。例如 clinical note summaries 中,遗漏 medication 是比表达差异更严重的错误。
你可以使用 sample code 对已部署 models 进行 benchmarking。下面的 benchmarking script 允许你基于自己的 specific use case 和 prompts,客观比较 models:
import time
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
# Initialize client
credential = DefaultAzureCredential()
project = AIProjectClient(
endpoint="https://<your-project-endpoint>.cognitiveservices.azure.com",
credential=credential
)
def benchmark_model(model_name, test_prompts):
"""Benchmark a model with test prompts"""
chat_client = project.models.get_chat_completions_client(model_name)
ModelEvaluator class 会包装一个 Foundry chat-completions client,并为每种 task type 暴露一个 evaluation method。每个 method 都遵循相同三步模式:遍历 labeled dataset,用 task-specific prompt template 调用 model,并设置 temperature=0 以保证 reproducibility,然后计算 standard metrics。我们从 classification evaluator 开始。
latencies = []
token_counts = []
for prompt in test_prompts:
start_time = time.time()
response = chat_client.complete(
messages=[{"role": "user", "content": prompt}],
max_tokens=500
)
latency = time.time() - start_time
latencies.append(latency)
token_counts.append(
response.usage.prompt_tokens + response.usage.completion_tokens
)
return {
"model": model_name,
"avg_latency": sum(latencies) / len(latencies),
"avg_tokens": sum(token_counts) / len(token_counts),
"total_cost_estimate": calculate_cost(model_name, token_counts)
}
Token counts 本身很难直观理解;我们真正想知道的是美元成本。下面的 helper 会基于每个 model 公布的 per-token pricing,将 token usage 转换为近似成本。Pricing 经常变化,在用这些数字进行 budget planning 前,请始终核对 Microsoft Foundry pricing page。
def calculate_cost(model_name, token_counts):
"""Calculate estimated cost based on token usage"""
# Pricing varies by model - check current rates
pricing = {
"gpt-4o": {"input": 0.005, "output": 0.015}, # per 1K tokens
"gpt-4o-mini": {"input": 0.0005, "output": 0.0015}
}
# Simplified calculation (actual cost depends on input/output ratio)
total_tokens = sum(token_counts)
avg_price = (pricing[model_name]["input"] + pricing[model_name]["output"]) / 2
定义好 benchmark 和 cost helpers 后,我们可以使用一组共享 representative prompts,在多个 models 之间运行比较。生产环境中,你应将这些 sample prompts 替换为实际 traffic 的代表性切片,通常是 50 到 200 个 prompts,覆盖 model 将遇到的全部 task 范围和 input lengths。
return (total_tokens / 1000) * avg_price
# Test with sample prompts
test_prompts = [
"Explain quantum computing in simple terms.",
"Write a Python function to calculate Fibonacci numbers.",
"Summarize the key benefits of cloud computing."
]
# Compare multiple models
models_to_test = ["gpt-4o", "gpt-4o-mini"]
results = []
for model in models_to_test:
result = benchmark_model(model, test_prompts)
results.append(result)
print(f"\n{model} Results:")
print(f" Average Latency: {result['avg_latency']:.2f}s")
print(f" Average Tokens: {result['avg_tokens']:.0f}")
print(f" Estimated Cost: ${result['total_cost_estimate']:.4f}")
Context window considerations
Context window 决定一个 model 在单次 request 中能处理多少信息。为了更好说明理解这个概念的必要性,我们来看一些基于常见 context size 的 use cases:
Small Context(< 8K tokens) :Simple Q&A、basic classification、short-form content。
Medium Context(8K–32K tokens) :Document summarization、code review、multi-turn conversations。
Large Context(32K–128K tokens) :Long document analysis、complex reasoning over multiple sources。
Extended Context(> 128K tokens) :Entire codebase analysis、book-length document processing。
一些热门 models 的 context window sizes,截至 2024–2025 年如下。在阅读列表前,最好先将 context windows 粗略分为三档,并理解每档适合的 workloads。Small(4K–16K tokens)适合 chat assistants、single-turn classification 和 short-form generation,因为你希望低延迟和低成本。Medium(32K–128K tokens)覆盖大多数 enterprise workloads,例如 multi-turn customer support、针对单篇文章或少量文档的 document Q&A,以及单文件 code review。Large(200K–1M+ tokens)适合 input 本身就是差异化因素的场景,例如带完整 longitudinal history 的 long clinical notes、跨很多 files 的 codebases,或汇聚 dozens of sources 的 research synthesis。
应将 model 匹配到你的任务所在的 bucket,而不是总是默认选择最大 context window。Oversizing window 会增加 latency 和 cost,但不一定增加 intelligence。
- GPT-4o:128,000 tokens
- GPT-4 Turbo:128,000 tokens
- GPT-4o-mini:16,385 tokens
- Llama 3.1 405B:128,000 tokens
- Claude 3.5 Sonnet:200,000 tokens
更大的 context windows 会消耗更多 tokens,并使每次 request 成本更高。只使用你真正需要的 context size。
Cost optimization strategies
有多种 production-grade cost optimization strategies 可以帮助你平衡 performance 和 cost,这对 production deployments 至关重要。下面探索一些业内常见的成本优化策略。
Strategy 1:Model cascading
对简单 queries 使用更小、更快的 models,并将更大 models 留给复杂任务。Model cascading 实现一种分层 model selection 方法,将简单 queries 路由到 cost-effective models,而只把真正需要高级 reasoning capabilities 的复杂任务交给 premium models。这种策略承认:并非所有 user queries 都需要同等程度的 model sophistication。一个关于 prescription refill policies 的简单 FAQ lookup,不需要与分析复杂 prior authorization denial 同样的计算能力。
考虑一个 healthcare benefits chatbot implementation:大多数 patient inquiries 都是关于 coverage details、appointment scheduling 或 basic eligibility 的常规问题,这些 queries smaller models 就可以有效处理。将 GPT-4o 或类似 advanced models 留给剩下 30% 的复杂 scenarios,例如 benefit comparisons、appeals guidance 或 multi-step care coordination,可以在不降低 patient experience 的情况下,将整体 token costs 降低 50% 或更多。
def intelligent_routing(user_query, complexity_threshold=0.7):
"""Route queries to appropriate models based on complexity"""
# Simple complexity analyzer (in production, use a trained classifier)
complexity_score = analyze_query_complexity(user_query)
if complexity_score < complexity_threshold:
# Use cost-effective model for simple queries
model_name = "gpt-4o-mini"
else:
# Use advanced model for complex queries
model_name = "gpt-4o"
chat_client = project.models.get_chat_completions_client(model_name)
response = chat_client.complete(
messages=[{"role": "user", "content": user_query}]
)
return response.choices[0].message.content
def analyze_query_complexity(query):
"""Analyze query complexity (simplified version)"""
# Factors that indicate complexity:
# - Query length
# - Number of questions
# - Technical terms
# - Request for reasoning or analysis
complexity_indicators = [
len(query.split()) > 50, # Long query
query.count('?') > 1, # Multiple questions
any(term in query.lower() for term in ['analyze', 'compare', 'evaluate', 'reasoning']),
any(term in query.lower() for term in ['technical', 'complex', 'detailed'])
]
return sum(complexity_indicators) / len(complexity_indicators)
intelligent_routing 函数接受 user query 和可选 complexity threshold,然后将 query 委派给 cost-effective model 或 advanced model:前者处理 routine queries,后者处理 complex scenarios。analyze_query_complexity helper function 会评估多个 indicators,包括 query length、question count、analytical terminology 和 technical vocabulary,从而生成 0 到 1 之间的 normalized complexity score。
在 production deployments 中,可以考虑用 trained classifier 替代 rule-based complexity analyzer。Foundry 的 Model Router feature 提供了 managed alternative,可以使用 machine learning 自动优化 routing decisions,并从你的特定 query patterns 中学习,以随时间提升 cost-quality tradeoffs。
Model cascading 需要仔细调优 threshold。如果 complexity threshold 设置得太高,复杂 queries 会被路由到 simpler models,降低 response quality,并可能在 regulated industries 中造成 compliance risks。如果设置得太低,则会消除 cost savings。应按 model tier 监控 quality metrics,例如 groundedness、relevance,并根据 evaluation results 调整 thresholds。
Strategy 2:Prompt compression
在保持 context 的同时降低 token usage。Token consumption 直接驱动 API costs,因此 context efficiency 是主要优化目标。许多 production scenarios 涉及处理长文档、维护 conversation history,或提供大量 system instructions;这些内容都会在 model 生成任何 response word 之前消耗 tokens。Prompt compression 通过 summarizing 或 condensing context,同时保留 accurate responses 所需的信息密度,来减少 input token counts。
Healthcare applications 在处理 patient records、clinical documentation 或跨数十页的 policy documents 时,经常遇到这一挑战。与其在每个 prompt 中包含完整 documents,不如使用 extractive summarization 将 context 压缩为 essential information。对于 document-grounded queries,这可以减少 60–80% 的 token usage。
下面的代码延续 Strategy 1 中引入的 healthcare assistant scenario,也就是一个基于 Foundry 的 chatbot,用于回答 clinicians 关于 patient records 和 policy documents 的问题。在这里,我们加入一个 extractive summarization step,它作为 source documents 的 preprocessing pass,使后续发给 model 的 prompts 只包含与 clinician question 相关的 sentences,而不是完整 document。结果是 prompts 更短、latency 更低、per-call cost 更低,同时不会丢失 model 准确回答所需的 clinical detail。
def compress_context(long_context, max_tokens=2000):
"""Compress long context using extractive summarization"""
# Use a smaller model for compression
compression_client = project.models.get_chat_completions_client("gpt-4o-mini")
compression_prompt = f"""Compress the following context into {max_tokens} tokens or less while preserving all critical information:
{long_context}
Compressed version:"""
response = compression_client.complete(
messages=[{"role": "user", "content": compression_prompt}],
max_tokens=max_tokens
)
return response.choices[0].message.content
# Use compressed context with main query
original_context = """[Very long document or conversation history]"""
compressed = compress_context(original_context, max_tokens=1500)
# Now use compressed version in main query
main_response = project.models.get_chat_completions_client("gpt-4o").complete(
messages=[
{"role": "system", "content": f"Context: {compressed}"},
{"role": "user", "content": "What are the main conclusions?"}
]
)
compress_context 函数使用 cost-effective model,也就是 GPT-4o-mini,执行 compression task。该任务通常比 primary query 需要更少 sophisticated reasoning。Compressed output 随后作为 main model 的 context,从而在保留关键信息用于准确 response generation 的同时,减少 total token count。
这种 two-stage approach 提供乘数级 cost savings:compression step 使用低成本 model,primary step 在大幅减少的 context 上运行。对于处理超过 10,000 tokens 文档的 applications,该策略可以在保持 response accuracy 在可接受阈值内的同时,将 per-query costs 降低 70% 或更多。
在继续之前,看一个 industry use case。一个 claims processing agent 需要引用一份 50 页的 benefits policy document。它可以在查询前将相关 sections 压缩到 2,000 tokens,把 context 从大约 15,000 tokens 降到原来的很小一部分。Compression model 会识别并保留 coverage limits、exclusion criteria 和 procedural requirements,同时消除冗余 legal language 和 formatting artifacts。
Strategy 3:Caching and deduplication
通过 intelligent caching 避免冗余 API calls。Redundant API calls 是纯浪费:相同 queries 返回相同 results,却支付完整成本。Production applications 经常遇到 repeated queries:多个 users 问同一个 FAQ question,batch processes 重新评估未变化的 documents,或者 conversation flows 重访之前的 context。实施 intelligent caching 可以消除这些冗余 calls,在提升 response latency 的同时,按 cache hit rate 比例降低成本。
下面的代码在 model client 前构建一个小型 in-process cache layer。目标很简单:当相同 prompt 第二次到达时,比如 FAQ-style queries、batch evaluations 或 shared dashboards 中常见,就从 cache 返回第二次调用,而不是再次为 model 付费。Cache key 是 full prompt 和 model parameters 的 hash,因此 request 中任何有意义的变化都会按设计导致 cache miss。
import hashlib
import json
from datetime import datetime, timedelta
class ResponseCache:
def __init__(self, ttl_minutes=60):
self.cache = {}
self.ttl = timedelta(minutes=ttl_minutes)
def get_cache_key(self, messages, model_name):
"""Generate cache key from messages and model"""
cache_content = json.dumps(
{
"model": model_name,
"messages": messages
},
sort_keys=True
)
return hashlib.md5(cache_content.encode()).hexdigest()
# Note: MD5 is used here only for cache-key generation (not security)
def get(self, messages, model_name):
"""Retrieve cached response if available and not expired"""
key = self.get_cache_key(messages, model_name)
if key in self.cache:
cached_response, timestamp = self.cache[key]
if datetime.now() - timestamp < self.ttl:
return cached_response
else:
del self.cache[key]
return None
def set(self, messages, model_name, response):
"""Cache a response"""
key = self.get_cache_key(messages, model_name)
self.cache[key] = (response, datetime.now())
# Usage
cache = ResponseCache(ttl_minutes=30)
def get_completion_with_cache(messages, model_name):
"""Get completion with caching"""
cached = cache.get(messages, model_name)
if cached:
print("Cache hit!")
return cached
chat_client = project.models.get_chat_completions_client(model_name)
response = chat_client.complete(messages=messages)
result = response.choices[0].message.content
cache.set(messages, model_name, result)
return result
def compress_context(long_context, max_tokens=2000):
"""Compress long context using extractive summarization"""
compression_client = project.models.get_chat_completions_client("gpt-4o-mini")
compression_prompt = f"""Compress the following context into {max_tokens} tokens or less while preserving all critical information:
{long_context}
Compressed version:"""
response = compression_client.complete(
messages=[{"role": "user", "content": compression_prompt}],
max_tokens=max_tokens
)
return response.choices[0].message.content
# Use compressed context with main query
original_context = """[Very long document or conversation history]"""
compressed = compress_context(original_context, max_tokens=1500)
main_response = project.models.get_chat_completions_client("gpt-4o").complete(
messages=[
{"role": "system", "content": f"Context: {compressed}"},
{"role": "user", "content": "What are the main conclusions?"}
]
)
ResponseCache class 实现了一个带 time-to-live(TTL)expiration 的 dictionary-based cache。get_cache_key method 会将 model name 和 message content 一起 hash,生成 unique identifier,确保发送到同一个 model 的 identical queries 共享 cache entries。get method 会检查 cached responses 并验证 expiration;set 则用 timestamps 存储 new responses。
get_completion_with_cache wrapper function 为 application code 提供 integration point。它会在发起 API calls 前检查 cache,并在 successful completions 后存储 responses。TTL mechanism 确保 cached responses 不会 stale,这对于 underlying data 会随时间变化的 applications 尤其重要。
Combining strategies for maximum impact
基于刚讨论的三种策略:model cascading、prompt compression 和 caching,组织可以通过将它们组合成一套 cohesive、layered optimization approach,进一步增强 cost efficiency 并最大化整体影响。
这三种策略组合后会产生协同效果。一个 production implementation 可能先检查 cache,识别 duplicate queries;然后应用 prompt compression 来减少 context size;最后使用 model cascading 将 compressed query 路由到合适的 model tier。这种 layered approach 会在多个层面处理 cost:
图 4.6:Cost optimization – layered query processing
Cache layer:完全消除 40–60% 的 redundant queries。
Compression layer:对 cache misses 将 token consumption 降低 60–80%。
Routing layer:将剩余 queries 的 70% 定向到 cost-effective models。
与 naive implementations 相比,这种组合效果可以将 AI operational costs 降低 80% 或更多。Naive implementation 通常把所有 queries 都发送到 premium models,使用完整 context,且没有 caching。
看一个实际例子:一个 hospital patient portal 每天接收 10,000 个 queries,成本分解可能如下:
Without optimization:10,000 queries × 平均 2,000 tokens × GPT-4o pricing = baseline cost。
With caching:4,000 unique queries,也就是 60% cache hit rate。
With compression:每个 query 平均 800 tokens,也就是所需 tokens 数减少 60%。
With cascading:1,200 queries 路由到 GPT-4o,2,800 queries 路由到 GPT-4o-mini。
Optimized implementation 可以用约 baseline cost 的 15–20% 处理相同 query volume,同时维持应用所需 quality thresholds。
在建立了如何通过 layered strategies 优化 cost 和 performance 之后,我们现在转向构建有效 AI systems 的另一个关键维度:如何与 models 沟通,并为它们提供正确的信息,以生成高质量 outputs。
Prompt engineering and context engineering
Prompt engineering 是构造 inputs,以诱导 language models 生成最佳 responses 的实践。本节将从基础技术逐步推进到高级策略。
Context engineering 与之相关但不同:prompt engineering 关注给 model 的 static instruction;context engineering 关注在 inference time 将哪些 additional information 加载进 model 的 context window,例如 retrieved documents、prior conversation turns、system-state summaries 和 tool output。实践中,两者会重叠,但这种区分很有用:prompt engineering 问的是 “我应该如何告诉 model 要做什么?”;context engineering 问的是 “model 需要知道什么,才能做好这件事?”
本节其余部分将按三层技术推进。我们从 basic prompt structure 开始,包括有效 prompt 的 anatomy 及其 components 顺序。然后介绍 advanced strategies,包括 chain-of-thought reasoning、few-shot learning 和 self-consistency prompting。最后转向 context management techniques,用于控制 inference time 到达 model 的信息,包括 sliding-window conversation pruning、用于 long-running sessions 的 semantic retrieval,以及 token-bounded workloads 下的 prompt compression。
Basic prompt structure
有效 prompt 通常遵循以下结构:
[System Context] + [Task Description] + [Input Data] + [Output Format] + [Constraints]
来看一个例子:
# Basic prompt structure
messages = [
{
"role": "system",
"content": "You are a helpful assistant specialized in data analysis."
},
{
"role": "user",
"content": """Task: Analyze the following sales data and identify trends.
Input Data:
Q1 2024: $1.2M revenue, 450 customers
Q2 2024: $1.8M revenue, 680 customers
Q3 2024: $2.1M revenue, 820 customers
Output Format: Provide analysis as bullet points.
Constraints: Focus only on revenue and customer growth trends.
(Reader's note: this Input Data section is the user-message payload that gets sent to the chatbot together with the prompt template defined above. It is not a continuation of the Python code; treat it as the conversation input you would feed to the agent at runtime, with the values populated from your real source system.)"""
}
]
这段代码展示了如何使用 messages format 向 model 发送 structured prompt,并获取 response。它展示了创建 chat client、传入 prepared prompt、打印 model generated output 的基本流程,有助于你验证 prompt 在实践中是否有效。
chat_client = project.models.get_chat_completions_client("gpt-4o")
response = chat_client.complete(messages=messages)
print(response.choices[0].message.content)
一旦我们理解了 prompt 的基本结构,就可以开始应用更高级的技术,引导 model 的 reasoning process,并提升 responses 质量。
Advanced prompt engineering techniques
Prompt engineering 中最常见的方法之一是 Chain-of-Thought(CoT)prompting,它鼓励 models 将复杂 reasoning 分解为步骤。CoT approach 会显著提升 reasoning tasks 上的 accuracy,尤其是复杂 mathematical 或 logical problems。
为了理解 Chain-of-Thought(CoT)prompting 的影响,我们比较一个 simple prompt 和一个显式引导 model step-by-step reasoning 的 prompt。关键区别在于,CoT prompts 鼓励 model 将问题分解为 intermediate steps,这通常会在 reasoning tasks 中带来更准确、更可靠的答案。
# Without Chain-of-Thought
basic_prompt = "If a store had 23 apples and sold 17, then received 45 more, how many apples does it have?"
# With Chain-of-Thought
cot_prompt = """If a store had 23 apples and sold 17, then received 45 more, how many apples does it have?
Let's solve this step by step:
1. Start with the initial number of apples
2. Subtract the apples sold
3. Add the apples received
4. Calculate the final total
Please show your work:"""
第一种情况下,model 被要求直接提供答案。简单问题中这可能可行,但在更复杂 scenarios 中可能导致错误。第二种情况下,prompt 会引导 model 走 reasoning process,通过显式化每个步骤提升 accuracy。
chat_client = project.models.get_chat_completions_client("gpt-4o")
response = chat_client.complete(
messages=[{"role": "user", "content": cot_prompt}]
)
print(response.choices[0].message.content)
另一种常用技术叫做 few-shot learning,即用户提供示例来引导 model behavior。Few-shot learning 的工作方式是直接在 prompt 中包含 2 到 5 个 demonstration examples,让 model 推断期望的 input-output pattern。它的好处是,无需任何 fine-tuning,也无需超出这些示例本身的 training data,就可以将 general-purpose model 适配到 domain-specific format,例如 structured extraction、一致 tone 或特定 response shape。
它的 trade-off 是,每多一个示例都会消耗 context window tokens。因此,few-shot prompts 适合用少量代表性示例就能可靠教会 model 的任务;如果某项任务需要数百个 examples 才能覆盖 variance,那么 fine-tuning 会是更好的选择。
Few-shot learning 通过少量 examples 引导 model 的 output format。这里的 prompt 展示了带标签 reviews,使 model 可以从新 review 中提取类似 structured information,并使用较低 temperature 提升 consistency。
few_shot_prompt = """Extract structured information from customer reviews.
Example 1:
Review: "Great product! Fast shipping. The blue color is beautiful."
Output: {"sentiment": "positive", "aspects": ["product quality", "shipping speed", "color"], "color_mentioned": "blue"}
Example 2:
Review: "Disappointed with quality. It took 2 weeks to arrive."
Output: {"sentiment": "negative", "aspects": ["product quality", "shipping speed"], "color_mentioned": null}
Example 3:
Review: "Decent value for money. I would buy again."
Output: {"sentiment": "positive", "aspects": ["value", "repurchase intent"], "color_mentioned": null}
Now extract information from this review:
Review: "The red one broke after a week. Customer service was unhelpful."
Output:"""
response = chat_client.complete(
messages=[{"role": "user", "content": few_shot_prompt}],
temperature=0.3 # Lower temperature for more consistent extraction
)
print(response.choices[0].message.content)
还有一种 technique 叫 self-consistency prompting,它会生成多个 reasoning paths,并选择最一致的答案。Self-consistency prompting 最好理解为 Chain-of-Thought(CoT)的一种泛化。CoT 中,你让 model step-by-step reasoning 一次,并接受它的单个答案。Self-consistency 中,你让 model step-by-step reasoning 多次,通常是 3–7 个 samples,并设置 non-zero temperature,使每个 sample 走不同路径,然后选择出现次数最多的答案。
其直觉是:在模型可能走多个 reasoning paths 的任务中,正确路径通常比任何特定错误路径更频繁被访问,因此在多个 paths 上进行 simple majority vote,通常比单次 sample 更可靠。相比 Few-Shot prompting,后者通过展示 input-output shape 提升 accuracy;相比 CoT,后者通过显式 reasoning 提升 accuracy;self-consistency 通过平滑单个 CoT sample 自带的 variance 提升 accuracy。
它的 trade-off 是成本:它会按 sample 数量成倍增加 token spend,因此应保留给 high-stakes calls,即额外可靠性值得成本的场景。这是一种常见 technique,适用于你预期 model 会生成 variable responses 的场景。
下面的代码分三个阶段实现 self-consistency pattern:第一,用 non-zero temperature 将同一个 prompt 发送给 model,生成 N 个独立 reasoning samples;第二,从每个 sample 中提取 final answer;第三,取 modal answer,也就是出现最频繁的答案,作为系统输出。下面三个短代码块分别对应这三个阶段。
def self_consistency_prompting(question, num_samples=5):
"""Use self-consistency to improve reasoning accuracy"""
prompt = f"""{question}
Let's approach this step-by-step:"""
responses = []
chat_client = project.models.get_chat_completions_client("gpt-4o")
# Generate multiple reasoning paths
for i in range(num_samples):
response = chat_client.complete(
messages=[{"role": "user", "content": prompt}],
temperature=0.7 # Some randomness for diverse reasoning
)
responses.append(response.choices[0].message.content)
# Aggregate responses (simplified - in production, use more sophisticated voting)
aggregation_prompt = f"""Given these {num_samples} different solutions to the same problem:
{"\n".join([f"Solution {i+1}:\n{resp}\n" for i, resp in enumerate(responses)])}
What is the most consistent and likely correct answer? Provide just the final answer."""
final_response = chat_client.complete(
messages=[{"role": "user", "content": aggregation_prompt}],
temperature=0.1 # Low temperature for final aggregation
)
return final_response.choices[0].message.content
# Example usage
question = "A farmer has 15 sheep. All but 8 die. How many sheep are left?"
answer = self_consistency_prompting(question, num_samples=5)
print(f"Final Answer: {answer}")
这种方法通过生成多个 reasoning paths,而不是依赖单个 response,来提升 accuracy。通过比较这些路径并选择最一致的答案,model 可以在复杂问题上生成更可靠结果。
有了 prompting techniques 之后,同样重要的是管理发送给 model 的信息量,以确保效率和性能。
Context window optimization
每个 language model 都运行在有限 context window 内,也就是它单次 request 能处理的最大 tokens 数。虽然 GPT-4o 等现代 models 支持 128,000 tokens 或更大的 context windows,但更大的 context 并不自动意味着更好的结果。高效管理 context windows 对 cost optimization 和 response quality 都非常关键:前者是因为每个 processed token 都需要付费;后者是因为 model 在过长 context 中可能难以定位相关信息。
Context window management 在 production applications 中尤其重要,尤其是维护 conversation history、处理长文档,或组合多个 information sources 的应用。一个 healthcare documentation assistant 如果累积 patient interaction history、clinical notes 和 policy references,很容易在单个 session 中超过 context limits。如果没有刻意设计的 context management,application 要么在触及 token limits 时失败,要么因为每次 request 都发送无关 historical context 而产生不必要成本。
Foundry applications 受益于两种主要 context optimization techniques:用于 conversation continuity 的 sliding window management,以及用于 intelligent context selection 的 semantic compression。这些方法可以降低 token consumption,同时保留 accurate、contextually aware responses 所需的信息密度。下面详细看这两种方法。
Technique 1:Sliding window context
对于 long conversations,只保留最近且最相关的 context。
Sliding-window technique 通过只保留 conversation history 中最近 N 次 exchanges,并丢弃更早的内容来工作。好处是 token usage 有明确上限:无论 conversation 运行多久,发送给 model 的 context 都不会超过一个可预测大小。Trade-off 是 conversation 早期的信息会对 model 不可见。对 transactional interactions,例如 appointment booking 或 FAQ-style Q&A,这通常可以接受;但对 stateful conversations,例如 ongoing clinical intake 或 multi-session tutoring,其中早期 context 很重要,就可能有问题。
下面的 ConversationManager class 使用可配置 window size 实现这一 pattern。
下面的 ConversationManager class 实现 sliding-window pattern。可以分三个逻辑块来看:第一块通过可配置的 max_history 和一个永远保留的 system message 槽位,初始化 class。第二块提供 add_message 和内部 pruning logic,在 window 满时丢弃最旧 user / assistant turns,同时将 system message 锚定在开头。第三块提供 get_messages_for_api,这是调用侧用于组装发送给 model 的最终 messages payload 的 helper。三个部分结合起来,让你在保持最近 turns 处于 context 中的同时,控制 token budget。
class ConversationManager:
def __init__(self, max_history=10):
self.messages = []
self.max_history = max_history
self.system_message = None
def set_system_message(self, content):
"""Set the system message (always retained)"""
self.system_message = {"role": "system", "content": content}
def add_message(self, role, content):
"""Add a message to the conversation"""
self.messages.append({"role": role, "content": content})
# Keep only recent messages (sliding window)
if len(self.messages) > self.max_history:
self.messages = self.messages[-self.max_history:]
def get_messages_for_api(self):
"""Get messages formatted for API call"""
if self.system_message:
return [self.system_message] + self.messages
return self.messages
def add_user_message(self, content):
"""Add user message"""
self.add_message("user", content)
def add_assistant_message(self, content):
"""Add assistant message"""
self.add_message("assistant", content)
# Usage
conversation = ConversationManager(max_history=8)
conversation.set_system_message("You are a helpful coding assistant.")
# Simulate a long conversation
conversation.add_user_message("How do I reverse a string in Python?")
conversation.add_assistant_message("You can use slicing: reversed_str = original[::-1]")
conversation.add_user_message("What about reversing a list?")
conversation.add_assistant_message("Same approach: reversed_list = original[::-1]")
# Get messages for next API call
messages = conversation.get_messages_for_api()
response = chat_client.complete(messages=messages)
Technique 2:Semantic compression
使用 embeddings 识别并保留最相关 context。
不同于 sliding-window pruning 只按 recency 保留 context,semantic retrieval 会根据与当前 query 的 topical relevance 保留 context。它的好处是,即使某些信息出现在 conversation 早期,只要与后续 response 语义相关,也仍然可以影响 later responses。这正是 stateful conversations 所需要的。代价是额外 infrastructure:你需要一个 embedding model,通常是 text-embedding-3-small 或 text-embedding-ada-002,一个用于 past messages 的 vector store,以及每轮对话中的 retrieval step。
实践中,对于超过大约 20 turns 的 conversations,或者不能接受丢失早期 context 的 applications,semantic retrieval 值得承担这些开销。
下面代码展示了如何使用 embeddings 和 similarity scoring 选择最相关的 past messages,确保只有 contextually useful information 被发送给 model。下面的代码实现 semantic context selection,而不是粗暴的 sliding-window pruning。思路是:为每条 prior message 生成 embedding,为当前 user query 生成 embedding,然后按 cosine similarity 对 past messages 排序,使 model 看到的是最语义相关的 turns,而不仅是最近 turns。
可以分三个逻辑块理解:第一块设置 get_embedding,通过 text-embedding-ada-002 deployment 获取任意文本的 vector。第二块定义 cosine_similarity,也就是用于评分两个 vectors 相关性的标准 normalized dot product。第三块将二者组合进 semantic_context_selection,它会将每条 prior message 与当前 query 比较评分,并返回 top_k 最相关 turns,供 chat model 使用。这种 pattern 可以在控制 long conversations 长度的同时,不丢失 simple recency-based pruning 会丢掉的相关信号。
from azure.ai.projects import AIProjectClient
import numpy as np
def get_embedding(text, model="text-embedding-ada-002"):
"""Get embedding for text"""
embedding_client = project.models.get_embeddings_client(model)
response = embedding_client.create(input=[text])
return response.data[0].embedding
def cosine_similarity(vec1, vec2):
"""Calculate cosine similarity between two vectors"""
vec1 = np.array(vec1)
vec2 = np.array(vec2)
return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
def semantic_context_selection(current_query, conversation_history, top_k=5):
"""Select most relevant messages from conversation history"""
query_embedding = get_embedding(current_query)
message_scores = []
for msg in conversation_history:
msg_embedding = get_embedding(msg["content"])
similarity = cosine_similarity(query_embedding, msg_embedding)
message_scores.append((msg, similarity))
message_scores.sort(key=lambda x: x[1], reverse=True)
relevant_messages = [msg for msg, score in message_scores[:top_k]]
return relevant_messages
conversation_history = [
{"role": "user", "content": "How do I deploy a model in Microsoft Foundry?"},
{"role": "assistant", "content": "You can deploy models using the portal or SDK..."},
{"role": "user", "content": "What's the difference between serverless and managed compute?"},
{"role": "assistant", "content": "Serverless is pay-per-use with automatic scaling..."},
{"role": "user", "content": "How do I fine-tune a model?"},
{"role": "assistant", "content": "Fine-tuning requires preparing training data..."},
]
current_query = "What are the cost differences between deployment options?"
relevant_context = semantic_context_selection(current_query, conversation_history, top_k=3)
messages = [{"role": "system", "content": "You are a Microsoft Foundry expert."}] + relevant_context + [{"role": "user", "content": current_query}]
response = chat_client.complete(messages=messages)
Evaluation models with Microsoft Foundry Evaluation
Microsoft Foundry 现在提供 end-to-end Evaluation capability,该能力自 2026 年 3 月 Foundry SDK 2.0 release 起 generally available。azure-ai-evaluation Python SDK 提供 out-of-the-box quality 和 safety evaluators,一个可以批量运行它们的 evaluate() function,以及一个 portal experience,用于聚合 per-row scores、judge-model reasoning 和 run-over-run comparisons。
本节其余部分将介绍这条 platform-native path:built-in evaluators、一个可运行的 healthcare example,以及当你的 domain 需要时如何添加 custom evaluator。
当你想通过 Evaluation process 评估 model 时,需要学习三个概念。
第一,evaluator。Evaluator 是一个 callable,用于给一行 data 打分,通常包括 query、model response,以及可选的 context,也就是 grounding documents,和 ground_truth,也就是 human reference answer。Azure AI Evaluation SDK 提供 built-in evaluators:用于 general quality 的 CoherenceEvaluator、FluencyEvaluator、RelevanceEvaluator;用于 grounding 的 GroundednessEvaluator、RetrievalEvaluator;用于 textual similarity 的 F1ScoreEvaluator、BleuScoreEvaluator;用于 risk and safety 的 ViolenceEvaluator、SelfHarmEvaluator、ContentSafetyEvaluator;以及用于 agentic patterns 的 ToolCallAccuracyEvaluator、TaskAdherenceEvaluator、IntentResolutionEvaluator。
第二,judge model。Quality evaluators 是 AI-assisted:它们会调用一个 model,通常是 gpt-4o 或 gpt-4o-mini,来完成 grading。你可以用 AzureOpenAIModelConfiguration 声明一次,并在 evaluators 之间复用。Judge model 不需要与被测 model 相同;常见做法是测试 gpt-4o-mini outputs,并让 gpt-4o 来评分。
第三,evaluate() function。这是 orchestrator:它读取 JSONL file,在所有 rows 上运行 evaluators,聚合 per-row 和 per-evaluator metrics,可选地将 run 记录到你的 Foundry project,并写出一个 JSON results file。下面我们先使用更简单的 single-row form,也就是直接调用 evaluator,然后再 scale up。
最小有用的 Foundry evaluation,是用一个 built-in evaluator 对一行数据打分。下面的代码用 Relevance Evaluator 对 clinical-note summary 打分,判断 response 是否回答了 query。
import os
from azure.ai.evaluation import RelevanceEvaluator, AzureOpenAIModelConfiguration
# Configure the judge model (the LLM that scores the response)
judge_config = AzureOpenAIModelConfiguration(
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
azure_deployment="gpt-4o",
api_version="2024-10-21",
)
# Initialize the built-in Relevance evaluator
relevance = RelevanceEvaluator(judge_config)
# Score one query/response pair
result = relevance(
query="Summarize this clinical note in one sentence: 62 y/o male with chest pain, EKG shows STEMI, started on aspirin and heparin.",
response="A 62-year-old man presenting with chest pain and an EKG consistent with STEMI was started on aspirin and heparin.",
)
print(result)
三行 setup,一次调用。Foundry-native pattern 看起来几乎像一个 unit test:导入 evaluator,给它一个 judge configuration,然后调用它。
图 4.7:A single-row Foundry evaluation with RelevanceEvaluator scores the response 5.0 on a 1-to-5 scale
Foundry 的 quality evaluators 会返回一个 score,这里是 5.0,也就是 1-to-5 scale 上的最高分;还会为了 backward compatibility 在 gpt_relevance key 下复制一份 score;返回 relevance reason field,其中包含 judge model 的 chain-of-thought explanation;返回基于 configurable threshold 的 binary pass / fail result,默认 threshold 为 3.0;并返回 threshold 本身,用于 traceability。
reason field 使这些 evaluators 具备 auditability:当某个 score 看起来不对时,你可以阅读 judge 为什么给出这个分数。
Scaling up:batches, custom evaluators, and the portal
Single-row scoring 适合 spot-checking 和 unit tests。对于 production work,你通常还需要三件事:从 JSONL file 运行几十到几百 rows;在一次 pass 中组合多个 evaluators;并将 run 记录到你的 Foundry project,使 team 可以在 portal 中看到结果。evaluate() function 可以完成这三件事。
你需要向它传入 JSONL data file、一个包含 evaluators 的 dictionary,这些 evaluators 可以是 built-in,也可以是自定义的;一个 column_mapping,用于告诉每个 evaluator 哪些 JSONL columns 对应哪些 parameters;你的 Foundry project endpoint;以及 results JSON 的 output path。
对于 agentic workflows,也就是后续章节会开发的内容,agentic evaluator family,包括 IntentResolutionEvaluator、ToolCallAccuracyEvaluator、TaskAdherenceEvaluator,会评估 multi-step agent behavior:agent 是否在行动前识别 intent、每次 tool call 是否使用了正确 parameters、整个 run 是否保持在任务上。它们消耗的 input shape 略有不同,也就是 agent 的 message history,而不是 query / response pair,但它们与 evaluate() 的组合方式相同。
Fine-Tuning and customization
Fine-tuning 通过在 domain-specific examples 上训练 foundation models,使其适配你的特定 use case。第 5 章将全面覆盖 fine-tuning techniques,包括 supervised fine-tuning(SFT)、direct preference optimization(DPO)和 reinforced fine-tuning(RFT)。本节提供实践指导,帮助判断 fine-tuning 何时比 prompt engineering 更有价值,何时 prompt engineering 已足够。
从高层看,Microsoft Foundry 中的 fine-tuning workflow 有四个阶段:data preparation,也就是将 training dataset 组装并验证为 JSONL format,并包含 system、user 和 assistant roles;training job creation,也就是选择 base model 和 hyperparameters,并通过 SDK 或 portal 提交 job;progress monitoring,也就是跟踪 loss curves 和 validation metrics,直到 job 完成;deployment,也就是通过与任何 catalog model 相同的 deployment modes,serverless API 或 managed compute,暴露 resulting fine-tuned model。
后续小节将依次介绍每个阶段,包括如何使用本章前面介绍的 evaluation framework,将 fine-tuned model 与 base model 进行评估对比。
When to Fine-Tune vs. prompt engineer
什么时候选择 fine-tuning,什么时候选择 prompt engineering,通常取决于 data availability 和 consistency requirements。
当你需要 rapid iteration、任务与 existing model capabilities 对齐、labeled data 有限,例如少于 100 个 examples,或 flexibility 比 consistency 更重要时,选择 prompt engineering。
当你拥有大量 labeled data,例如 500–1000+ examples,需要 consistent formatting 或 behavior,需要通过 learned shortcuts 降低 token usage,必须嵌入 domain-specific knowledge,或者 scale 下的 cost optimization 足以证明 upfront training investment 合理时,选择 fine-tuning。
例如,一个 healthcare organization 如果需要在每天数千个 queries 中使用精确 medical terminology 和一致 response formats,将从 fine-tuning 中受益。一个 marketing team 如果正在测试不同 content approaches,则会受益于 prompt engineering 的 flexibility。
Fine-Tuning workflow overview
Fine-tuning process 遵循四个阶段:
图 4.8:Fine-tuning workflow in Microsoft Foundry
Data preparation、training job creation、progress monitoring 和 deployment:Data preparation 要求将 ongoing conversation 中的 examples 格式化为 JSONL format,每个 example 包含 system instructions、user input 和期望的 assistant response。Quality 比 quantity 更重要:500 个精心构造的 examples,胜过 5,000 个不一致 examples。
Training job creation:Training configuration 涉及选择 hyperparameters:epochs,通常为 2–4;batch size,影响 memory 和 convergence;learning rate multiplier,较低值用于 subtle adaptations,较高值用于 significant behavioral changes。Foundry 的 serverless fine-tuning 会自动处理 infrastructure provisioning。
Progress monitoring:Monitoring 会通过 Foundry portal 或 SDK 跟踪 training progress,显示 loss curves 和 validation metrics。Training duration 通常从几十分钟到数小时不等,取决于 dataset size 和 model complexity。
Deployment:Deployment 为 fine-tuned model 创建 endpoint,可通过与 base models 相同的 SDK interfaces 访问。使用 descriptive naming conventions,例如 "contoso-support-v1",以跟踪 model versions。
Evaluating Fine-Tuned models
始终在 held-out test set 上,将 fine-tuned models 与其 base model 进行 benchmark。比较 accuracy、F1 和 task-specific metrics,以量化 improvement。Fine-tuned model 应在你的 target task 上展现可衡量收益;如果 performance 持平或更差,就需要调整 training data 或 hyperparameters。
除了 accuracy,还应评估 response consistency、对 formatting requirements 的遵守,以及 domain terminology usage。这些往往正是 fine-tuning 的主要动机。随着 user queries 出现 distribution shift,fine-tuned model effectiveness 可能下降,因此还应持续监控 production performance。
Fine-tuning 是一种投资。当你有足够高质量数据、清晰 consistency requirements,并且 query volumes 足以证明 upfront effort 合理时,它就会带来回报。应先从 prompt engineering 开始验证方法,然后在触及其限制时再 fine-tune。
Case studies
本节展示 model catalog exploration 和 evaluation 在不同行业中的真实应用,并综合运用本章学习的所有 concepts 和 techniques。
每个 case study 都采用一致结构:描述 problem 和 constraints;基于本章前面建立的 criteria 逐步进行 model selection;展示产生可接受 quality 的 prompt engineering choices;最后呈现支持 production decision 的 evaluation results。按顺序阅读这些案例,可以看到同一个 framework 如何应用到非常不同的 healthcare use cases 中。
Case study 1:Clinical note summarization
一家区域医院系统每份 discharge summary 大约消耗 20 分钟 physician time,每月大约生成 15,000 份 summaries。他们希望在不损失 clinical accuracy 或 compliance posture 的前提下,降低每份 summary 的时间成本。最终决策是使用 Foundry 的 gpt-4o 进行 first-draft summarization,并配合 domain-tuned prompt template;然后将 draft 送入 custom evaluator,对 diagnosis preservation 和 dosage accuracy 进行评分;只有超过 confidence threshold 的 summaries 才会呈现给 physician,供其一键接受。
下面的内容总结了这一决策带来的 requirements、model choice、prompt design、evaluation strategy 和 outcomes。本 case study 中,我们将考察一个 healthcare provider,它需要总结冗长 clinical notes,帮助 doctors 快速查看 patient histories。
Model selection
评估了 GPT-4、GPT-4o 和 GPT-4o-mini models,最终选择 GPT-4o,因为它在 accuracy 和 cost 之间取得了平衡。128K tokens 的 context window 可以容纳较长 clinical notes。
Accuracy 和 cost requirements 由两个 healthcare-specific constraints 决定。在 accuracy 方面,clinical summary 中遗漏相关 diagnosis、medication 或 follow-up instruction 可能直接影响 patient care,因此 team 要求相对于 clinician-authored reference summaries 的 ROUGE-L score 高于 0.45,并且在 held-out safety subset 中 medications 零遗漏。
在 cost 方面,预计每月大约生成 40,000 份 summaries,每份 summary 平均 3,000 input tokens 和 800 output tokens。
Prompt engineering
在这个 context 中,prompt engineering 聚焦于仔细结构化 instructions,使 model 生成准确、一致且符合 domain 的 outputs。这包括清楚定义 task、expected format,以及任何 domain constraints,例如 medical terminology 或必须包含的 critical information。
下面的 prompt template 使用 Few-Shot approach:在 user 的 clinical note 前,我们提供两个已完成的 input / output examples,展示我们希望 model 遵循的形态。这里选择 Few-Shot 而不是 zero-shot,是因为 clinical summarization 有医院 downstream systems 期望的特定格式,包括 sections、bullet structure 和 abbreviation policy。向 model 展示两个正确格式的 examples,比单纯用 instructions 描述格式更能产生一致 output。
我们没有对这个 prompt 采用 CoT 或 self-consistency,因为该任务是 structural reformatting,而不是 multi-step reasoning。额外 reasoning steps 对这个 ground truth 主要来自 source 的任务,并不会带来 accuracy 收益。
Summary:"""
def summarize_clinical_note(note):
chat_client = project.models.get_chat_completions_client("gpt-4o")
prompt = clinical_summary_template.format(clinical_note=note)
response = chat_client.complete(
messages=[
{
"role": "system",
"content": "You are a medical documentation specialist. Always maintain patient confidentiality and use precise medical terminology."
},
{"role": "user", "content": prompt}
],
temperature=0.1
)
return response.choices[0].message.content
sample_note = """
Patient: 65-year-old male presenting with chest pain and shortness of breath.
History: Hypertension, Type 2 Diabetes, previous MI in 2020.
Vital Signs: BP 145/92, HR 88, Temp 98.6F, SpO2 94% on room air.
Assessment: Elevated troponin levels, ECG shows ST elevation in leads II, III, aVF.
Diagnosis: Acute inferior STEMI.
Treatment: Administered aspirin 325mg, clopidogrel 600mg loading dose. Patient transferred to cath lab for emergency PCI. Cardiologist Dr. Smith notified.
Medications: Metoprolol 50mg BID, Lisinopril 10mg daily, Metformin 1000mg BID.
"""
summary = summarize_clinical_note(sample_note)
print(summary)
图 4.9:Clinical Note Summarization output
回顾一下,上面的代码展示了 clinical-note summarization 中的 prompt-template pattern,并使用 temperature=0.1 提升 output consistency。在 production deployment 中,你会将结果接入 EHR 的 task list,而不是 print statement;针对每份 summary 使用 custom safety evaluator 打分;并添加 feedback loop,让 physician edits 回流到 evaluator 的 training data 中。
Evaluation
我们评估了 100 个 model-generated summaries,对照的是来自 de-identified、IRB-approved 的机构 clinical notes 子集中的 board-certified physician-authored gold-standard summaries。每一对 summary 都在三个维度上评分,每个维度都有明确的定义和 pass threshold,使结果可以 audit。
Completeness 由 custom Python evaluator 评分,检查所有 required fields 是否存在,包括 chief complaint、diagnosis、每个 active medication、vital signs 和 treatment plan。这里使用 explicit field-presence rules,而不是 LLM-as-judge grader。我们选择 rule-based check,是因为 LLM judges 在 omission detection 上不可靠:当 summary 缺少的内容恰好是 clinician 需要的关键信息时,它们仍可能将 partial summary 评分为 “mostly complete”。Completeness 的通过阈值是 100%。
Accuracy 使用 Foundry GroundednessEvaluator 评分,并将 original clinical note 作为 context。该指标衡量 summary 中的 dosages、diagnosis codes 和 care-plan items 是否由 source note 支持,而不是 confabulated。评分范围为 1 到 5;我们设置 pass threshold 为 4。
Readability 使用 Foundry CoherenceEvaluator 评分,并结合一个 domain-specific check,检查是否存在接收 clinician 预期的标准 discharge-summary section headers,包括 Chief Complaint、History、Vitals、Assessment、Plan、Medications。我们选择这三个 metrics,而不是更 generic 的 Foundry quality bundle,是因为它们直接对应 chief medical officer 在 readiness review 中指出的 failure modes:missing diagnoses 会延误 downstream care;inaccurate dosages 会造成 patient safety incidents;不熟悉的 formatting 会迫使接收 clinician 重新阅读 source summary。Coherence 的通过阈值是 4,section-header check 的通过阈值是 100%。
94% 这个数字表示 100 份 summaries 中有 94 份同时通过全部三个 thresholds。6 个失败案例中,4 个是 missing-medication errors,也就是 source note 中存在的 active medication 未出现在 summary 中;2 个是 over-abbreviated diagnosis sections,也就是 diagnosis 技术上正确,但压缩得过度,接收 clinician 如果不重新打开 source note,就无法采取行动。这两类 failure modes 直接推动了下一轮 prompt template 迭代:我们加入了明确 instructions,要求枚举每个 active medication,并在首次引用时完整写出 diagnoses。
Results
建模过程带来的关键结果如下:
- Documentation review time 降低 60%。
- 改善 shifts 之间的 handoff communication。
- 将 Microsoft Foundry 的 enterprise security features 作为其更广泛 HIPAA compliance strategy 的一部分加以利用。
从这个 case study 中,我们学到:将正确 model selection 与设计良好的 prompt engineering 结合,可以在规模化条件下生成准确且结构化的 clinical summaries。这种方法有助于提升效率,同时维持 healthcare applications 所需的质量。
Medical AI applications 需要额外 validation 和 regulatory compliance,并且绝不应替代 professional medical judgment。
Case study 2:Quality control analysis in manufacturing
现在来看下一个挑战。一家 manufacturing company 需要分析多个 production lines 的 quality control reports,以识别 patterns 并预测 defects。和前面一样,我们会逐步走完整个过程,然后讨论 outcomes。
Model selection
GPT-4o 用于 complex analysis tasks。text-embedding-ada-002 model 用于跨 historical reports 做 semantic search。为了 cost optimization,还实现了 model cascading。
上面提到的 complex-analysis tasks,是跨 encounter summaries,会拉取每个 patient 的 3–6 次 prior visits,以及 multi-document chart reviews,会综合 labs、imaging 和 clinician notes。这些正是 smaller model 会丢失 fidelity 的输入:到文档中段时,smaller model 开始混淆不同 visits 的 findings,或丢失早期 documents 中的细节。
我们进行的 cost calculus 假设 gpt-4o tokens 的 per-token price 约为 gpt-4o-mini 的 5 倍,并且根据 prompt-length 和 task-class profiling,大约 30% traffic 需要 larger model。gpt-4o 的 200K-token effective context window 是硬性要求,因为最长的 chart reviews 超过 90K tokens 的 compiled context。
Implementation
下面的代码实现了上面描述的 multi-document chart review。它使用 hybrid approach:一个小型 embedding-based retrieval pass 会从 patient full history 中缩小相关 prior encounters 范围;随后,一个带 chart-review template 的 Few-Shot prompt 生成 synthesis。我们不需要 CoT 或 self-consistency,因为 synthesis 是 structural,也就是将 retrieved passages 合并进 report sections,而不是对内容做 multi-hop reasoning。
class QualityControlAnalyzer:
def __init__(self, project_client):
self.project = project_client
self.analysis_client = project_client.models.get_chat_completions_client("gpt-4o")
self.embedding_client = project_client.models.get_embeddings_client("text-embedding-ada-002")
self.historical_reports = []
Analyzer 同时保留两个 Foundry clients:gpt-4o 用于对单个 defect reports 进行 structured narrative analysis;text-embedding-ada-002 用于跨 historical report corpus 做 semantic search。在 production 中,historical_reports list 会从 database 或 blob store 填充;这里为了清晰起见,将其保存在 memory 中。该 class 暴露三个 operations:single-report analysis、similar-defect lookup 和 trend prediction。下面依次介绍。
def analyze_defect_report(self, report_text):
"""Analyze a single defect report"""
analysis_prompt = f"""Analyze this manufacturing quality control report:
{report_text}
Provide analysis in this format:
1. Defect Type: [Classification]
2. Severity: [Low/Medium/High/Critical]
3. Root Cause: [Likely cause based on description]
4. Recommended Actions: [Specific steps to prevent recurrence]
5. Related Components: [List affected parts/systems]
Analysis:"""
response = self.analysis_client.complete(
messages=[
{
"role": "system",
"content": "You are a manufacturing quality control expert with expertise in root cause analysis."
},
{"role": "user", "content": analysis_prompt}
],
temperature=0.2
)
return response.choices[0].message.content
第二个 operation 使用 embedding-based semantic search 查找相似 historical defects。这很有价值,因为同一个 underlying cause 经常以表层 wording 的变化呈现出来。今天一位 engineer 对 defect 的描述方式,可能与六个月前另一位同事不同,但 embedding space 会捕获这种 semantic similarity。
def find_similar_defects(self, current_report, top_k=5):
"""Find similar historical defects using semantic search"""
# Get embedding for current report
current_embedding = self.embedding_client.create(
input=[current_report]
).data[0].embedding
# Find similar historical reports
similarities = []
for historical in self.historical_reports:
hist_embedding = self.embedding_client.create(
input=[historical['text']]
).data[0].embedding
similarity = cosine_similarity(current_embedding, hist_embedding)
similarities.append((historical, similarity))
# Return top-k most similar
similarities.sort(key=lambda x: x[1], reverse=True)
return [report for report, score in similarities[:top_k]]
第三个 operation 会聚合一组 recent reports,以便在问题升级为 line stoppages 之前预测 emerging trends。analyze_defect_report 处理单个 report,而 predict_defect_trend 接收一个 recent reports window,通常是过去 7 到 30 天,并要求 model 识别 patterns、emerging issues 和 priority areas for intervention。
def predict_defect_trend(self, recent_reports):
"""Predict defect trends from recent reports"""
trend_prompt = f"""Based on these recent quality control reports, identify trends and predict potential issues:
{"\n".join([f"Report {i+1}: {r}" for i, r in enumerate(recent_reports)])}
Provide:
1. Identified Trends: [Patterns across reports]
2. Emerging Issues: [Potential problems before they escalate]
3. Preventive Recommendations: [Actions to take now]
4. Priority Areas: [What to focus on immediately]
Analysis:"""
response = self.analysis_client.complete(
messages=[{"role": "user", "content": trend_prompt}],
temperature=0.3
)
return response.choices[0].message.content
# Usage
qc_analyzer = QualityControlAnalyzer(project)
defect_report = """
Production Line: Assembly Line 3
Date: 2024-12-15
Issue: Misaligned bracket on chassis assembly, noticed during final inspection
Frequency: 12 units out of 100 in current batch
Impact: Requires manual adjustment, adding 3 minutes per unit
Shift: Night shift (10pm-6am)
Operator Notes: Issue appeared after routine maintenance on robotic arm
"""
# Analyze current defect
analysis = qc_analyzer.analyze_defect_report(defect_report)
print("Defect Analysis:")
print(analysis)
# Find similar historical issues
similar_defects = qc_analyzer.find_similar_defects(defect_report, top_k=3)
print("\nSimilar Historical Defects:")
for i, defect in enumerate(similar_defects, 1):
print(f"{i}. {defect['summary']}")
图 4.10:Quality-control defect-analysis output。模型生成结构化五段式 root-cause analysis
Results
Defect-analysis agent 会在每次 quality engineer 提交 defect report 时运行。它会从 embeddings index 中检索三个最相近的 historical defects,生成基于这些相邻案例的 root-cause hypothesis,并将所有内容展示为一张 triage card,使 engineer 可以在几分钟内采取行动。
下面的 metrics 描述了该 workflow 在 pilot deployment 中对 team overall throughput 的影响。这些 metrics 包括 throughput、defect-reduction 和 scheduling metrics。我们使用这些指标来展示 workflow improvement 的数量级和形态;你应在自己的部署中 instrument 真实环境以测量实际数字,并将任何对外发布的数据都视为需要测量而不是估算的内容。
Defect-analysis time 从每份 report 大约 30 分钟,下降到每份 report 大约 3 分钟。前者是 quality engineer 阅读 report、从 shared drive 中查找类似 past incidents,并撰写 root-cause hypothesis;后者是 engineer review agent output、接受或修改,并将其路由给 responsible team。这是约 10 倍 reduction,与其他 GenAI-augmented manufacturing QC deployments 公开结果一致。
Predictive maintenance scheduling 首次变得可行,因为 agent 的 trend-prediction output 给 maintenance team 提供了 forward-looking view,能看到哪些 lines 和 components 正在向 failure 漂移,而不只是 backward-looking 地查看已经 broken 的内容。
从这个 case study 中,我们学到:将 prompt-based analysis 与 embeddings 结合,既可以深度检查单个 defects,也可以跨 historical data 检测 patterns。
这种方法帮助我们从 reactive issue handling 转向 proactive decision-making,从而提升效率并减少 recurring defects。
Case study 3:Technical documentation generation
在这个 case study 中,我们考察一家 semiconductor company,它需要为数千个 components 生成并维护 technical documentation。我们继续逐步走完整个 solution。
Model selection
GPT-4o 用于 comprehensive documentation generation。Fine-tuned GPT-4o-mini model 用于 consistent formatting 和 terminology。
在 cost 方面,决定性因素是该团队每季度约生成 2,000 页 component pages。如果每页都使用 gpt-4o,会超出团队预算大约 4 倍,因此我们将 high-stakes synthesis steps 路由到 gpt-4o,将 formatting / normalization steps 路由到 fine-tuned gpt-4o-mini。
Fine-tuning 本身使用 Foundry 的 supervised fine-tuning workflow,基于一个包含 1,200 个 component documentation examples 的 dataset,这些 examples 已由团队手动标准化。目标是教会 smaller model 遵循公司的 house style,包括 section ordering、terminology choices 和 abbreviation policy,而不是扩展它的 general capability。Custom evaluation metrics 用于评估 technical accuracy。
Documentation pipeline
下面的代码以三个逻辑块实现上面描述的 manufacturing documentation agent。第一块加载 component specifications 和 historical-template library。第二块调用 fine-tuned gpt-4o-mini 进行 formatting / normalization pass,然后升级到 gpt-4o,执行 synthesis pass,将 formatted sections 组合成 final document。第三块运行 validation pass,将 generated document 与 structured specifications 对照,并将任何 drift 暴露给 engineer review。
import json
class TechnicalDocGenerator:
def __init__(self, project_client):
self.project = project_client
self.base_client = project_client.models.get_chat_completions_client("gpt-4o")
def generate_component_docs(self, component_specs):
"""Generate technical documentation from component specifications"""
doc_prompt = f"""Generate comprehensive technical documentation for this semiconductor component:
Specifications:
{json.dumps(component_specs, indent=2)}
Generate documentation with these sections:
1. Overview: High-level description and purpose
2. Technical Specifications: Detailed specs in table format
3. Operating Conditions: Temperature, voltage, current ranges
4. Pin Configuration: Pin diagram description and functions
5. Application Notes: Typical usage scenarios
6. Safety and Compliance: Relevant standards and certifications
Use precise technical language. Include all numerical specifications."""
response = self.base_client.complete(
messages=[
{
"role": "system",
"content": "You are a technical documentation specialist for semiconductor components. Use precise engineering terminology and IEEE documentation standards."
},
{"role": "user", "content": doc_prompt}
],
temperature=0.2
)
return response.choices[0].message.content
def validate_documentation(self, generated_docs, original_specs):
"""Validate generated documentation against original specs"""
validation_prompt = f"""Review this generated documentation for accuracy:
Original Specifications:
{json.dumps(original_specs, indent=2)}
Generated Documentation:{generated_docs}
Check for:
1. Accuracy: Are all specifications correctly represented?
2. Completeness: Are all required sections present?
3. Consistency: Is terminology consistent?
4. Standards Compliance: Does it follow IEEE documentation standards?
Provide validation report with any discrepancies found."""
response = self.base_client.complete(
messages=[{"role": "user", "content": validation_prompt}],
temperature=0.1
)
return response.choices[0].message.content
doc_generator = TechnicalDocGenerator(project)
component_specs = {
"part_number": "SC-2847X",
"type": "Power Management IC",
"voltage_input": "3.0V - 5.5V",
"voltage_output": "1.2V - 3.3V (adjustable)",
"current_max": "3A",
"efficiency": "95%",
"operating_temp": "-40°C to +125°C",
"package": "QFN-24",
"features": ["Integrated FETs", "Over-current protection", "Thermal shutdown"]
}
documentation = doc_generator.generate_component_docs(component_specs)
print("Generated Documentation:")
print(documentation)
validation = doc_generator.validate_documentation(documentation, component_specs)
print("\nValidation Report:")
print(validation)
图 4.11:Technical-documentation generation output。Agent 根据 SC-2847X specification dictionary 生成六段式 IEEE-style component datasheet
Fine-Tuning for consistency
Base gpt-4o-mini model 可以生成技术上正确的 documentation,但不同 component 之间在 terminology、section ordering 和 table formatting 上不一致。Fine-tuning 用于将 model 固定到公司的 documentation conventions 上。
Fine-tuning 采用 supervised 方式,使用 1,200 个 prompt / completion pairs。这些 pairs 来自公司 house style 中由人工 review 的 datasheets,base model 为 gpt-4o-mini。最终 checkpoint 会在一个 held-out 的 300-example test split 上验证,这部分 examples 在 tuning 期间 model 从未见过。
Format consistency,也就是通过 structural diff 对照公司 document template 自动评分,达到约 98%。Technical accuracy 由三位独立 domain-expert reviewers 按四分制 rubric 手动评分,并要求至少两位 reviewers 给出最高分才算通过,最终达到约 92%。
与前面 case studies 中的 metrics 一样,这些是与公开 deployments 对齐的 illustrative figures,而不是来自单一具名客户的 measured numbers。请在你自己的部署中 instrument 真实环境,以测量实际数字。
Results
- Documentation creation 从每个 component 大约 4 小时,下降到每个 component 大约 20 分钟。
- 通过 pipeline 生成的 5,000 多份 datasheets 中,format 和 terminology consistency 得以保持。
- 过去需要数天 manual rewrites 的 specification updates,在受影响 datasheets 被重新生成后,只需几分钟即可完成。
关键结论是:prompt engineering 和 fine-tuning 是互补的。Base model 上的 prompt engineering 负责 per-component generation logic,并且快速可迭代;fine-tuning 则负责不应漂移的 consistency floor。
Summary
本章最重要的结论是:model selection 是 workflow decision,而不是 checkbox。某个任务的正确 model,取决于你的 context size、cost envelope、users 能容忍的 latency,以及你愿意接受的 failure modes。
还有三个关键结论。
第一,prompt engineering 和 model selection 是联合决策。一个使用 GPT-4o-mini 的 Few-Shot prompt,经常会优于一个使用 GPT-4o 的 zero-shot prompt;而正确组合取决于具体 workload。
第二,evaluation 会告诉你 prompt-and-model choice 是否有效。Foundry built-in evaluators 可以给你 baseline,但 production workloads 几乎总是需要 custom evaluators,这些 evaluators 要针对你的 domain 中真实 failure modes 调优。
第三,本章中的 case studies,包括 clinical-note summarization、manufacturing quality control 和 technical documentation generation,都是如何端到端组合三件事的模板:catalog selection、prompt design 和 evaluation。
当你进入后续 agent-focused chapters 时,请记住这三个结论:你即将学习的 agent capabilities,是建立在 model 和 prompt choices 之上的,而本章技术正是帮助你做出好选择的方法。
本章探索了 Microsoft Foundry Model Catalog,以及如何通过 portal 和 SDK 浏览其 1,800+ models,截至 2026 年初,涵盖 foundation models、open-source options 和 specialized variants。我们考察了 selection criteria,包括 task alignment、performance metrics、context window requirements,以及 model cascading 和 prompt compression 等 cost optimization strategies。
我们覆盖了 prompt engineering techniques,从 basic structured prompts,到 advanced methods,包括 chain-of-thought reasoning、few-shot learning、self-consistency prompting,以及使用 sliding windows 和 semantic compression 的 context optimization。我们讨论了 Microsoft Foundry 现在内置的 evaluation。我们也学习了何时 fine-tune,何时 prompt engineer,并走过了 data preparation、hyperparameter tuning,以及与 base models 做 performance comparison 的实践 workflows。
Case studies 展示了 healthcare、manufacturing 和 high-tech scenarios 中的成功实施,并展示了多个 use cases 中显著的效率提升。