mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Fix Eval samples (#4033)
* fix red team sample * Updated self-reflection * fix for workflow eval sample * fix test
This commit is contained in:
committed by
GitHub
Unverified
parent
6a39d5a652
commit
aab80d9ed9
@@ -7,23 +7,22 @@ This sample demonstrates the self-reflection pattern using Agent Framework and A
|
||||
**What it demonstrates:**
|
||||
- Iterative self-reflection loop that automatically improves responses based on groundedness evaluation
|
||||
- Batch processing of prompts from JSONL files with progress tracking
|
||||
- Using `AzureOpenAIChatClient` with Azure CLI authentication
|
||||
- Using `AzureOpenAIResponsesClient` with a Project Endpoint and Azure CLI authentication
|
||||
- Comprehensive summary statistics and detailed result tracking
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Azure Resources
|
||||
- **Azure OpenAI**: Deploy models (default: gpt-4.1 for both agent and judge)
|
||||
- **Azure OpenAI Responses in Foundry**: Deploy models (default: gpt-5.2 for both agent and judge)
|
||||
- **Azure CLI**: Run `az login` to authenticate
|
||||
|
||||
### Python Environment
|
||||
```bash
|
||||
pip install agent-framework-core azure-ai-projects pandas --pre
|
||||
pip install agent-framework-core pandas --pre
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
```bash
|
||||
# .env file
|
||||
AZURE_AI_PROJECT_ENDPOINT=https://<your-ai-resource>.services.ai.azure.com/api/projects/<your-ai-project>/
|
||||
```
|
||||
|
||||
@@ -67,6 +66,12 @@ The agent iteratively improves responses:
|
||||
✓ Completed with score: 5/5 (best at iteration 2/3)
|
||||
```
|
||||
|
||||
In the Foundry UI, under `Build`/`Evaluations` you can view detailed results for each prompt, including:
|
||||
- Context
|
||||
- Query
|
||||
- Response
|
||||
- Groundedness scores and reasoning for each interation of each prompt
|
||||
|
||||
## Related Resources
|
||||
|
||||
- [Reflexion Paper](https://arxiv.org/abs/2303.11366)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# requires-python = ">=3.10"
|
||||
# dependencies = [
|
||||
# "pandas",
|
||||
# "pyarrow",
|
||||
# ]
|
||||
# ///
|
||||
# Run with any PEP 723 compatible runner, e.g.:
|
||||
@@ -13,12 +14,13 @@ import argparse
|
||||
import asyncio
|
||||
import os
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import openai
|
||||
import pandas as pd
|
||||
from agent_framework import Agent, Message
|
||||
from agent_framework.azure import AzureOpenAIChatClient
|
||||
from agent_framework.azure import AzureOpenAIResponsesClient
|
||||
from azure.ai.projects import AIProjectClient
|
||||
from azure.identity import AzureCliCredential
|
||||
from dotenv import load_dotenv
|
||||
@@ -50,11 +52,38 @@ Usage as CLI with extra options:
|
||||
--output resources/results.jsonl \\
|
||||
--max-reflections 3 \\
|
||||
-n 10 # Optional: process only first 10 prompts
|
||||
|
||||
=============== Example output ===============
|
||||
|
||||
============================================================
|
||||
SUMMARY
|
||||
============================================================
|
||||
Total prompts processed: 31
|
||||
✓ Successful: 30
|
||||
✗ Failed: 1
|
||||
|
||||
Groundedness Scores:
|
||||
Average best score: 4.77/5
|
||||
Perfect scores (5/5): 25/30 (83.3%)
|
||||
|
||||
Improvement Analysis:
|
||||
Average first score: 4.50/5
|
||||
Average final score: 4.70/5
|
||||
Average improvement: +0.20
|
||||
Responses that improved: 4/30 (13.3%)
|
||||
|
||||
Iteration Statistics:
|
||||
Average best iteration: 1.17
|
||||
Best on first try: 25/30 (83.3%)
|
||||
============================================================
|
||||
|
||||
✓ Processing complete!
|
||||
|
||||
"""
|
||||
|
||||
|
||||
DEFAULT_AGENT_MODEL = "gpt-4.1"
|
||||
DEFAULT_JUDGE_MODEL = "gpt-4.1"
|
||||
DEFAULT_AGENT_MODEL = "gpt-5.2"
|
||||
DEFAULT_JUDGE_MODEL = "gpt-5.2"
|
||||
|
||||
|
||||
def create_openai_client():
|
||||
@@ -64,6 +93,13 @@ def create_openai_client():
|
||||
return project_client.get_openai_client()
|
||||
|
||||
|
||||
def create_async_project_client():
|
||||
from azure.ai.projects.aio import AIProjectClient as AsyncAIProjectClient
|
||||
from azure.identity.aio import AzureCliCredential as AsyncAzureCliCredential
|
||||
|
||||
return AsyncAIProjectClient(endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"], credential=AsyncAzureCliCredential())
|
||||
|
||||
|
||||
def create_eval(client: openai.OpenAI, judge_model: str) -> openai.types.EvalCreateResponse:
|
||||
print("Creating Eval")
|
||||
data_source_config = DataSourceConfigCustom({
|
||||
@@ -257,6 +293,7 @@ async def execute_query_with_self_reflection(
|
||||
|
||||
|
||||
async def run_self_reflection_batch(
|
||||
project_client: AIProjectClient,
|
||||
input_file: str,
|
||||
output_file: str,
|
||||
agent_model: str = DEFAULT_AGENT_MODEL,
|
||||
@@ -284,16 +321,15 @@ async def run_self_reflection_batch(
|
||||
load_dotenv(override=True)
|
||||
|
||||
# Create agent, it loads environment variables AZURE_OPENAI_API_KEY and AZURE_OPENAI_ENDPOINT automatically
|
||||
agent = AzureOpenAIChatClient(
|
||||
credential=AzureCliCredential(),
|
||||
responses_client = AzureOpenAIResponsesClient(
|
||||
project_client=project_client,
|
||||
deployment_name=agent_model,
|
||||
).as_agent(
|
||||
instructions="You are a helpful agent.",
|
||||
)
|
||||
|
||||
# Load input data
|
||||
print(f"Loading prompts from: {input_file}")
|
||||
df = pd.read_json(input_file, lines=True)
|
||||
input_path = (Path(__file__).parent / input_file).resolve()
|
||||
print(f"Loading prompts from: {input_path}")
|
||||
df = pd.read_json(path_or_buf=input_path, lines=True, engine="pyarrow")
|
||||
print(f"Loaded {len(df)} prompts")
|
||||
|
||||
# Apply limit if specified
|
||||
@@ -332,7 +368,7 @@ async def run_self_reflection_batch(
|
||||
try:
|
||||
result = await execute_query_with_self_reflection(
|
||||
client=client,
|
||||
agent=agent,
|
||||
agent=responses_client.as_agent(instructions=row["system_instruction"]),
|
||||
eval_object=eval_object,
|
||||
full_user_query=row["full_prompt"],
|
||||
context=row["context_document"],
|
||||
@@ -386,8 +422,9 @@ async def run_self_reflection_batch(
|
||||
# Create DataFrame and save
|
||||
results_df = pd.DataFrame(results)
|
||||
|
||||
print(f"\nSaving results to: {output_file}")
|
||||
results_df.to_json(output_file, orient="records", lines=True)
|
||||
output_path = (Path(__file__).parent / output_file).resolve()
|
||||
print(f"\nSaving results to: {output_path}")
|
||||
results_df.to_json(output_path, orient="records", lines=True)
|
||||
|
||||
# Generate detailed summary
|
||||
successful_runs = results_df[results_df["error"].isna()]
|
||||
@@ -482,6 +519,7 @@ async def main():
|
||||
# Run the batch processing
|
||||
try:
|
||||
await run_self_reflection_batch(
|
||||
project_client=create_async_project_client(),
|
||||
input_file=args.input,
|
||||
output_file=args.output,
|
||||
agent_model=args.agent_model,
|
||||
@@ -499,4 +537,4 @@ async def main():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
exit(asyncio.run(main()))
|
||||
asyncio.run(main())
|
||||
|
||||
Reference in New Issue
Block a user