🎯 核心主题:Pydantic数据验证与结构化输出
📅 更新时间:2024年
📊 难度等级:⭐⭐⭐(中级)


目录


一、什么是Pydantic

1.1 Pydantic简介

Pydantic 是Python中最流行的数据验证库,它使用Python类型注解来运行时验证数据。

Pydantic核心功能

数据验证

数据解析

数据序列化

类型提示

自动类型检查

自定义验证器

错误处理

JSON解析

字典转换

对象映射

JSON序列化

字典导出

格式控制

IDE支持

代码补全

静态检查

1.2 Pydantic核心特性

1. 数据验证

from pydantic import BaseModel, validator
from typing import List, Optional

class Question(BaseModel):
    """题目数据模型"""
    title: str                    # 题干
    answer: str                   # 答案
    analysis: str                 # 解析
    difficulty: str               # 难度
    knowledge_points: List[str]   # 知识点列表
    
    @validator('difficulty')
    def validate_difficulty(cls, v):
        """验证难度等级"""
        if v not in ['简单', '中等', '困难']:
            raise ValueError('难度必须是:简单、中等、困难')
        return v

# 使用示例
question_data = {
    "title": "1+1=?",
    "answer": "2",
    "analysis": "基础加法运算",
    "difficulty": "简单",
    "knowledge_points": ["加法", "基础运算"]
}

question = Question(**question_data)
print(question.title)  # 输出: 1+1=?

2. 自动类型转换

from pydantic import BaseModel

class Student(BaseModel):
    name: str
    age: int
    score: float

# 自动类型转换
student = Student(name="张三", age="20", score="95.5")
print(student.age)    # 输出: 20 (int)
print(student.score)  # 输出: 95.5 (float)

3. JSON序列化

# 转换为字典
student_dict = student.dict()
print(student_dict)
# 输出: {'name': '张三', 'age': 20, 'score': 95.5}

# 转换为JSON
student_json = student.json()
print(student_json)
# 输出: {"name": "张三", "age": 20, "score": 95.5}

1.3 Pydantic vs 传统方式

Pydantic方式

自动验证

类型安全

代码简洁

易于维护

传统方式

手动验证

容易出错

代码冗长

难以维护

对比示例:

# ❌ 传统方式:手动验证
def create_question(data):
    # 手动验证每个字段
    if not isinstance(data.get('title'), str):
        raise ValueError('title必须是字符串')
    if not isinstance(data.get('answer'), str):
        raise ValueError('answer必须是字符串')
    if data.get('difficulty') not in ['简单', '中等', '困难']:
        raise ValueError('难度不合法')
    
    # 手动构建对象
    question = {
        'title': data['title'],
        'answer': data['answer'],
        'difficulty': data['difficulty']
    }
    return question

# ✅ Pydantic方式:自动验证
class Question(BaseModel):
    title: str
    answer: str
    difficulty: str

question = Question(**data)  # 自动验证和类型转换

二、Pydantic在Agent构建中的作用

2.1 Agent架构中的数据流

用户输入

Agent处理

大模型

原始输出

Pydantic验证

结构化数据

工具调用

返回用户

2.2 Pydantic在Agent中的核心作用

作用1:结构化LLM输出

效果

解决方案

问题

LLM输出不可控
格式不统一
难以解析

Pydantic定义
输出格式

输出结构化
格式统一
易于处理

代码示例:

from pydantic import BaseModel, Field
from typing import List
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate

# 1. 定义输出结构
class QuestionOutput(BaseModel):
    """题目生成输出结构"""
    title: str = Field(description="题干内容")
    options: List[str] = Field(description="选项列表")
    answer: str = Field(description="正确答案")
    analysis: str = Field(description="题目解析")
    difficulty: str = Field(description="难度等级")
    knowledge_points: List[str] = Field(description="知识点列表")

# 2. 创建解析器
parser = PydanticOutputParser(pydantic_object=QuestionOutput)

# 3. 构建Prompt
prompt = PromptTemplate(
    template="请生成一道{subject}题目。\n{format_instructions}",
    input_variables=["subject"],
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

# 4. 调用LLM
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(model="gpt-4")

# 生成Prompt
_input = prompt.format(subject="数学")

# 获取LLM输出
output = llm.invoke(_input)

# 5. 解析为结构化数据
question = parser.parse(output.content)

print(question.title)  # 题干
print(question.answer)  # 答案
print(question.analysis)  # 解析

Prompt中的格式说明:

请生成一道数学题目。

输出格式:
{
  "title": "题干内容",
  "options": ["选项A", "选项B", "选项C", "选项D"],
  "answer": "正确答案",
  "analysis": "题目解析",
  "difficulty": "难度等级",
  "knowledge_points": ["知识点1", "知识点2"]
}
作用2:工具调用参数验证

验证通过

验证失败

Agent决策

工具选择

参数提取

Pydantic验证

工具执行

错误处理

代码示例:

from pydantic import BaseModel, validator
from typing import Optional
from langchain.tools import BaseTool

# 1. 定义工具参数结构
class QuestionGeneratorInput(BaseModel):
    """题目生成工具的输入参数"""
    grade: str = Field(description="年级")
    subject: str = Field(description="科目")
    topic: str = Field(description="知识点")
    difficulty: str = Field(description="难度", default="中等")
    question_type: str = Field(description="题型", default="选择题")
    
    @validator('difficulty')
    def validate_difficulty(cls, v):
        """验证难度"""
        if v not in ['简单', '中等', '困难']:
            raise ValueError('难度必须是:简单、中等、困难')
        return v
    
    @validator('question_type')
    def validate_question_type(cls, v):
        """验证题型"""
        if v not in ['选择题', '填空题', '简答题']:
            raise ValueError('题型必须是:选择题、填空题、简答题')
        return v

# 2. 定义工具
class QuestionGeneratorTool(BaseTool):
    name = "question_generator"
    description = "生成教育题目"
    args_schema: type[BaseModel] = QuestionGeneratorInput
    
    def _run(
        self,
        grade: str,
        subject: str,
        topic: str,
        difficulty: str = "中等",
        question_type: str = "选择题"
    ):
        # 参数已通过Pydantic验证
        # 执行题目生成逻辑
        return self.generate_question(grade, subject, topic, difficulty, question_type)

# 3. Agent调用工具
from langchain.agents import initialize_agent

tools = [QuestionGeneratorTool()]
agent = initialize_agent(tools, llm, agent="structured-chat-zero-shot-react-description")

# Agent会自动使用Pydantic验证参数
result = agent.run("请生成一道高一数学关于二次函数的中等难度选择题")
作用3:多Agent数据传递

出题Agent

Pydantic验证

结构化数据

审题Agent

Pydantic验证

结构化数据

阅题Agent

代码示例:

from pydantic import BaseModel
from typing import List

# 1. 定义Agent间传递的数据结构
class QuestionData(BaseModel):
    """题目数据"""
    question_id: str
    title: str
    answer: str
    analysis: str
    difficulty: str
    knowledge_points: List[str]

class ReviewResult(BaseModel):
    """审题结果"""
    question_id: str
    quality_score: float
    issues: List[str]
    suggestions: List[str]
    approved: bool

class GradingResult(BaseModel):
    """阅题结果"""
    question_id: str
    student_answer: str
    is_correct: bool
    score: float
    feedback: str

# 2. Agent实现
class QuestionAgent:
    """出题Agent"""
    def generate(self, params: dict) -> QuestionData:
        # 生成题目
        raw_output = self.llm.invoke(params)
        # 使用Pydantic结构化输出
        return QuestionData(**raw_output)

class ReviewAgent:
    """审题Agent"""
    def review(self, question: QuestionData) -> ReviewResult:
        # 审核题目
        raw_output = self.llm.invoke(question.dict())
        # 使用Pydantic结构化输出
        return ReviewResult(**raw_output)

class GradingAgent:
    """阅题Agent"""
    def grade(self, question: QuestionData, student_answer: str) -> GradingResult:
        # 批阅答案
        raw_output = self.llm.invoke({
            "question": question.dict(),
            "student_answer": student_answer
        })
        # 使用Pydantic结构化输出
        return GradingResult(**raw_output)

# 3. Agent协作流程
question_agent = QuestionAgent()
review_agent = ReviewAgent()
grading_agent = GradingAgent()

# 出题
question = question_agent.generate({
    "grade": "高一",
    "subject": "数学",
    "topic": "二次函数"
})

# 审题
review_result = review_agent.review(question)

# 阅题
grading_result = grading_agent.grade(question, "x=2")

2.3 Pydantic在Agent中的优势

Pydantic优势

数据安全

开发效率

代码质量

团队协作

自动验证

类型安全

错误处理

减少样板代码

自动序列化

IDE支持

代码简洁

易于维护

可读性强

接口规范

文档自动生成

类型提示

优势详解:

优势 说明 示例
数据安全 自动验证数据类型和格式 防止LLM输出格式错误
开发效率 减少手动验证代码 自动类型转换和序列化
代码质量 类型提示提高可读性 IDE自动补全和检查
团队协作 统一数据接口规范 自动生成API文档

三、小E项目中的数据结构化输出

3.1 项目中的Pydantic应用场景

小E项目Pydantic应用

题目生成

QuestionOutput

题目审核

ReviewOutput

题目解析

AnalysisOutput

题目批阅

GradingOutput

学情报告

ReportOutput

知识图谱

KnowledgeGraph

3.2 具体实现代码

场景1:AI出题的结构化输出
from pydantic import BaseModel, Field, validator
from typing import List, Optional
from enum import Enum

# 1. 定义枚举类型
class DifficultyLevel(str, Enum):
    """难度等级"""
    EASY = "简单"
    MEDIUM = "中等"
    HARD = "困难"

class QuestionType(str, Enum):
    """题型"""
    CHOICE = "选择题"
    FILL = "填空题"
    SHORT_ANSWER = "简答题"

# 2. 定义题目输出结构
class QuestionOutput(BaseModel):
    """AI出题的结构化输出"""
    title: str = Field(
        ...,
        description="题干内容",
        example="已知二次函数f(x) = x² - 4x + 3,求f(x)的最小值。"
    )
    question_type: QuestionType = Field(
        ...,
        description="题目类型"
    )
    options: Optional[List[str]] = Field(
        None,
        description="选项列表(仅选择题需要)",
        example=["A. -1", "B. 0", "C. 1", "D. 3"]
    )
    answer: str = Field(
        ...,
        description="正确答案",
        example="A"
    )
    analysis: str = Field(
        ...,
        description="题目解析",
        example="将二次函数配方:f(x) = (x-2)² - 1,当x=2时取得最小值-1。"
    )
    difficulty: DifficultyLevel = Field(
        ...,
        description="难度等级"
    )
    knowledge_points: List[str] = Field(
        ...,
        description="知识点列表",
        example=["二次函数", "配方法", "最值问题"]
    )
    estimated_time: int = Field(
        ...,
        description="预计答题时间(分钟)",
        ge=1,
        le=60
    )
    
    @validator('options')
    def validate_options(cls, v, values):
        """验证选项(选择题必须有选项)"""
        if values.get('question_type') == QuestionType.CHOICE and not v:
            raise ValueError('选择题必须有选项')
        return v
    
    class Config:
        """Pydantic配置"""
        use_enum_values = True
        schema_extra = {
            "example": {
                "title": "已知二次函数f(x) = x² - 4x + 3,求f(x)的最小值。",
                "question_type": "选择题",
                "options": ["A. -1", "B. 0", "C. 1", "D. 3"],
                "answer": "A",
                "analysis": "将二次函数配方:f(x) = (x-2)² - 1,当x=2时取得最小值-1。",
                "difficulty": "中等",
                "knowledge_points": ["二次函数", "配方法", "最值问题"],
                "estimated_time": 5
            }
        }

# 3. 使用LangChain的PydanticOutputParser
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI

# 创建解析器
parser = PydanticOutputParser(pydantic_object=QuestionOutput)

# 创建Prompt
prompt = PromptTemplate(
    template="""
你是一位专业的教育出题专家。请根据以下要求生成一道高质量题目。

要求:
- 年级:{grade}
- 科目:{subject}
- 知识点:{topic}
- 难度:{difficulty}
- 题型:{question_type}

{format_instructions}

请生成题目:
""",
    input_variables=["grade", "subject", "topic", "difficulty", "question_type"],
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

# 调用LLM
llm = ChatOpenAI(model="gpt-4", temperature=0.7)

# 生成题目
_input = prompt.format(
    grade="高一",
    subject="数学",
    topic="二次函数的最值问题",
    difficulty="中等",
    question_type="选择题"
)

output = llm.invoke(_input)

# 解析为结构化数据
question = parser.parse(output.content)

print(f"题干: {question.title}")
print(f"答案: {question.answer}")
print(f"解析: {question.analysis}")
print(f"知识点: {question.knowledge_points}")
场景2:AI审题的结构化输出
from pydantic import BaseModel, Field
from typing import List
from enum import Enum

class QualityLevel(str, Enum):
    """质量等级"""
    EXCELLENT = "优秀"
    GOOD = "良好"
    MEDIUM = "中等"
    POOR = "较差"

class ReviewOutput(BaseModel):
    """AI审题的结构化输出"""
    question_id: str = Field(..., description="题目ID")
    
    # 质量评估
    quality_level: QualityLevel = Field(..., description="质量等级")
    quality_score: float = Field(
        ...,
        description="质量评分(0-100)",
        ge=0,
        le=100
    )
    
    # 详细评价
    content_evaluation: str = Field(..., description="内容评价")
    knowledge_accuracy: str = Field(..., description="知识点准确性评价")
    difficulty_appropriateness: str = Field(..., description="难度适切性评价")
    
    # 问题与建议
    issues: List[str] = Field(
        ...,
        description="存在的问题",
        example=["题干表述不够清晰", "选项干扰项设计不合理"]
    )
    suggestions: List[str] = Field(
        ...,
        description="优化建议",
        example=["建议重新表述题干", "建议增加干扰项的迷惑性"]
    )
    
    # 审核结论
    approved: bool = Field(..., description="是否通过审核")
    needs_revision: bool = Field(..., description="是否需要修改")
    
    @validator('quality_score')
    def validate_score(cls, v, values):
        """验证质量评分与等级的一致性"""
        quality_level = values.get('quality_level')
        if quality_level == QualityLevel.EXCELLENT and v < 90:
            raise ValueError('优秀等级的评分应不低于90分')
        if quality_level == QualityLevel.POOR and v >= 60:
            raise ValueError('较差等级的评分应低于60分')
        return v

# 使用示例
review_data = {
    "question_id": "q001",
    "quality_level": "良好",
    "quality_score": 85,
    "content_evaluation": "题目内容设计合理,考查目标明确",
    "knowledge_accuracy": "知识点标注准确,覆盖全面",
    "difficulty_appropriateness": "难度适中,符合目标学生水平",
    "issues": ["选项B的干扰性较弱"],
    "suggestions": ["建议优化选项B,增加迷惑性"],
    "approved": True,
    "needs_revision": True
}

review = ReviewOutput(**review_data)
print(f"质量等级: {review.quality_level}")
print(f"质量评分: {review.quality_score}")
print(f"是否通过: {review.approved}")
场景3:AI阅题的结构化输出
from pydantic import BaseModel, Field
from typing import List, Optional

class GradingOutput(BaseModel):
    """AI阅题的结构化输出"""
    question_id: str = Field(..., description="题目ID")
    student_id: str = Field(..., description="学生ID")
    
    # 答题情况
    student_answer: str = Field(..., description="学生答案")
    is_correct: bool = Field(..., description="是否正确")
    score: float = Field(..., description="得分", ge=0)
    
    # 错误分析(仅错误时)
    error_type: Optional[str] = Field(
        None,
        description="错误类型",
        example="概念理解错误"
    )
    error_analysis: Optional[str] = Field(
        None,
        description="错误原因分析",
        example="学生混淆了二次函数的开口方向"
    )
    
    # 知识点诊断
    weak_knowledge_points: List[str] = Field(
        ...,
        description="薄弱知识点",
        example=["二次函数图像", "配方法"]
    )
    
    # 学习建议
    study_suggestions: List[str] = Field(
        ...,
        description="学习建议",
        example=["复习二次函数的基本性质", "多做配方法练习题"]
    )
    recommended_questions: List[str] = Field(
        ...,
        description="推荐练习题目ID",
        example=["q002", "q003", "q004"]
    )
    
    # 反馈内容
    feedback: str = Field(
        ...,
        description="给学生的反馈",
        example="这道题考查的是二次函数的最值问题..."
    )

# 使用示例
grading_data = {
    "question_id": "q001",
    "student_id": "s001",
    "student_answer": "B",
    "is_correct": False,
    "score": 0,
    "error_type": "计算错误",
    "error_analysis": "学生在配方过程中出现计算错误",
    "weak_knowledge_points": ["配方法", "二次函数最值"],
    "study_suggestions": [
        "复习配方法的步骤",
        "多做配方练习题",
        "注意计算准确性"
    ],
    "recommended_questions": ["q002", "q003"],
    "feedback": "这道题考查的是二次函数的最值问题。你选择了B选项,说明在配方过程中出现了计算错误。建议你重新复习配方法的步骤,特别注意符号的处理。"
}

grading = GradingOutput(**grading_data)
print(f"是否正确: {grading.is_correct}")
print(f"错误类型: {grading.error_type}")
print(f"薄弱知识点: {grading.weak_knowledge_points}")
场景4:学情报告的结构化输出
from pydantic import BaseModel, Field
from typing import List, Dict
from datetime import datetime

class KnowledgePointMastery(BaseModel):
    """知识点掌握情况"""
    knowledge_point: str = Field(..., description="知识点名称")
    mastery_level: float = Field(
        ...,
        description="掌握程度(0-100)",
        ge=0,
        le=100
    )
    practice_count: int = Field(..., description="练习次数")
    correct_rate: float = Field(
        ...,
        description="正确率(0-1)",
        ge=0,
        le=1
    )

class LearningReport(BaseModel):
    """学情报告的结构化输出"""
    student_id: str = Field(..., description="学生ID")
    report_date: datetime = Field(..., description="报告日期")
    report_type: str = Field(..., description="报告类型:日报/周报/月报")
    
    # 整体情况
    total_questions: int = Field(..., description="总答题数")
    correct_rate: float = Field(
        ...,
        description="整体正确率(0-1)",
        ge=0,
        le=1
    )
    average_time: float = Field(..., description="平均答题时间(分钟)")
    
    # 知识点掌握情况
    knowledge_mastery: List[KnowledgePointMastery] = Field(
        ...,
        description="各知识点掌握情况"
    )
    
    # 薄弱环节
    weak_points: List[str] = Field(
        ...,
        description="薄弱知识点",
        example=["二次函数", "不等式"]
    )
    
    # 进步情况
    improvement_areas: List[str] = Field(
        ...,
        description="进步明显的领域",
        example=["函数图像", "方程求解"]
    )
    
    # 学习建议
    study_plan: str = Field(
        ...,
        description="个性化学习计划",
        example="建议重点复习二次函数的图像性质..."
    )
    recommended_resources: List[str] = Field(
        ...,
        description="推荐学习资源",
        example=["视频课程:二次函数基础", "练习题集:二次函数专项训练"]
    )
    
    # 能力评估
    ability_scores: Dict[str, float] = Field(
        ...,
        description="各能力维度得分",
        example={
            "逻辑推理": 85,
            "计算能力": 90,
            "问题解决": 80
        }
    )

# 使用示例
report_data = {
    "student_id": "s001",
    "report_date": datetime.now(),
    "report_type": "周报",
    "total_questions": 50,
    "correct_rate": 0.85,
    "average_time": 3.5,
    "knowledge_mastery": [
        {
            "knowledge_point": "二次函数",
            "mastery_level": 75,
            "practice_count": 15,
            "correct_rate": 0.73
        },
        {
            "knowledge_point": "不等式",
            "mastery_level": 90,
            "practice_count": 10,
            "correct_rate": 0.90
        }
    ],
    "weak_points": ["二次函数"],
    "improvement_areas": ["不等式", "方程求解"],
    "study_plan": "建议重点复习二次函数的图像性质,多做配方法练习题",
    "recommended_resources": [
        "视频课程:二次函数基础",
        "练习题集:二次函数专项训练"
    ],
    "ability_scores": {
        "逻辑推理": 85,
        "计算能力": 90,
        "问题解决": 80
    }
}

report = LearningReport(**report_data)
print(f"总答题数: {report.total_questions}")
print(f"正确率: {report.correct_rate * 100}%")
print(f"薄弱知识点: {report.weak_points}")

3.3 项目中的数据流

数据层

Pydantic验证层

Agent层

用户层

教师出题

学生答题

出题Agent

审题Agent

阅题Agent

报告Agent

QuestionOutput

ReviewOutput

GradingOutput

LearningReport

题目数据库

答题记录

学情数据


四、实战案例

4.1 完整的Agent实现

from pydantic import BaseModel, Field, validator
from typing import List, Optional
from langchain.chat_models import ChatOpenAI
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from langchain.tools import BaseTool
from langchain.agents import AgentExecutor, create_structured_chat_agent
import json

# ==================== 1. 定义数据模型 ====================

class QuestionInput(BaseModel):
    """出题工具输入参数"""
    grade: str = Field(description="年级")
    subject: str = Field(description="科目")
    topic: str = Field(description="知识点")
    difficulty: str = Field(description="难度", default="中等")
    question_type: str = Field(description="题型", default="选择题")

class QuestionOutput(BaseModel):
    """出题工具输出结果"""
    title: str = Field(description="题干")
    options: Optional[List[str]] = Field(None, description="选项")
    answer: str = Field(description="答案")
    analysis: str = Field(description="解析")
    knowledge_points: List[str] = Field(description="知识点")

# ==================== 2. 定义工具 ====================

class QuestionGeneratorTool(BaseTool):
    """题目生成工具"""
    name = "question_generator"
    description = "生成教育题目"
    args_schema: type[BaseModel] = QuestionInput
    
    def _run(self, grade: str, subject: str, topic: str, 
             difficulty: str = "中等", question_type: str = "选择题"):
        # 创建LLM
        llm = ChatOpenAI(model="gpt-4", temperature=0.7)
        
        # 创建解析器
        parser = PydanticOutputParser(pydantic_object=QuestionOutput)
        
        # 创建Prompt
        prompt = PromptTemplate(
            template="""
你是一位专业的教育出题专家。请根据以下要求生成一道高质量题目。

要求:
- 年级:{grade}
- 科目:{subject}
- 知识点:{topic}
- 难度:{difficulty}
- 题型:{question_type}

{format_instructions}

请生成题目:
""",
            input_variables=["grade", "subject", "topic", "difficulty", "question_type"],
            partial_variables={"format_instructions": parser.get_format_instructions()}
        )
        
        # 调用LLM
        _input = prompt.format(
            grade=grade,
            subject=subject,
            topic=topic,
            difficulty=difficulty,
            question_type=question_type
        )
        
        output = llm.invoke(_input)
        
        # 解析为结构化数据
        question = parser.parse(output.content)
        
        return question.dict()

# ==================== 3. 创建Agent ====================

from langchain.agents import initialize_agent, AgentType

# 创建LLM
llm = ChatOpenAI(model="gpt-4", temperature=0)

# 创建工具列表
tools = [QuestionGeneratorTool()]

# 创建Agent
agent = initialize_agent(
    tools=tools,
    llm=llm,
    agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True
)

# ==================== 4. 使用Agent ====================

# 运行Agent
result = agent.run("请生成一道高一数学关于二次函数的中等难度选择题")

# 解析结果
question = QuestionOutput(**eval(result))

print(f"题干: {question.title}")
print(f"答案: {question.answer}")
print(f"解析: {question.analysis}")
print(f"知识点: {question.knowledge_points}")

4.2 多Agent协作案例

from pydantic import BaseModel, Field
from typing import List
from langchain.chat_models import ChatOpenAI
from langchain.output_parsers import PydanticOutputParser

# ==================== 1. 定义数据模型 ====================

class Question(BaseModel):
    """题目数据"""
    title: str
    answer: str
    analysis: str
    knowledge_points: List[str]

class ReviewResult(BaseModel):
    """审核结果"""
    quality_score: float = Field(ge=0, le=100)
    issues: List[str]
    approved: bool

class GradingResult(BaseModel):
    """批阅结果"""
    is_correct: bool
    feedback: str
    weak_points: List[str]

# ==================== 2. 定义Agent ====================

class QuestionAgent:
    """出题Agent"""
    def __init__(self):
        self.llm = ChatOpenAI(model="gpt-4")
        self.parser = PydanticOutputParser(pydantic_object=Question)
    
    def generate(self, topic: str) -> Question:
        prompt = f"请生成一道关于{topic}的题目。\n{self.parser.get_format_instructions()}"
        output = self.llm.invoke(prompt)
        return self.parser.parse(output.content)

class ReviewAgent:
    """审题Agent"""
    def __init__(self):
        self.llm = ChatOpenAI(model="gpt-4")
        self.parser = PydanticOutputParser(pydantic_object=ReviewResult)
    
    def review(self, question: Question) -> ReviewResult:
        prompt = f"请审核以下题目:\n{question.json()}\n{self.parser.get_format_instructions()}"
        output = self.llm.invoke(prompt)
        return self.parser.parse(output.content)

class GradingAgent:
    """阅题Agent"""
    def __init__(self):
        self.llm = ChatOpenAI(model="gpt-4")
        self.parser = PydanticOutputParser(pydantic_object=GradingResult)
    
    def grade(self, question: Question, student_answer: str) -> GradingResult:
        prompt = f"""
题目:{question.json()}
学生答案:{student_answer}

请批阅学生的答案。
{self.parser.get_format_instructions()}
"""
        output = self.llm.invoke(prompt)
        return self.parser.parse(output.content)

# ==================== 3. Agent协作 ====================

# 创建Agent
question_agent = QuestionAgent()
review_agent = ReviewAgent()
grading_agent = GradingAgent()

# 出题
question = question_agent.generate("二次函数")

# 审题
review_result = review_agent.review(question)

# 如果审核通过,进行批阅
if review_result.approved:
    grading_result = grading_agent.grade(question, "x=2")
    print(f"批阅结果: {grading_result.is_correct}")
    print(f"反馈: {grading_result.feedback}")
else:
    print(f"题目未通过审核,问题:{review_result.issues}")

五、最佳实践

5.1 Pydantic使用建议

Pydantic最佳实践

模型设计

验证规则

错误处理

性能优化

字段命名清晰

合理使用Optional

添加Field描述

自定义验证器

字段间验证

枚举类型

捕获ValidationError

友好的错误信息

日志记录

避免复杂验证

使用parse_obj

缓存模型

5.2 常见问题与解决方案

问题 原因 解决方案
LLM输出格式错误 LLM未按格式输出 使用PydanticOutputParser
字段验证失败 数据类型不匹配 添加自定义验证器
枚举值错误 枚举值不在范围内 使用Enum类型
Optional字段处理 字段可能为None 使用Optional类型
嵌套模型复杂 多层嵌套难以维护 拆分为多个模型

5.3 性能优化建议

# ❌ 不好的做法:每次都重新解析
for data in data_list:
    model = MyModel(**data)  # 每次都重新解析

# ✅ 好的做法:批量解析
from pydantic import parse_obj_as

models = parse_obj_as(List[MyModel], data_list)  # 批量解析

# ✅ 使用模型缓存
from functools import lru_cache

@lru_cache(maxsize=100)
def get_model(model_name: str):
    return get_model_class(model_name)

六、总结

6.1 Pydantic在Agent中的核心价值

Pydantic核心价值

数据安全

开发效率

代码质量

团队协作

✅ 自动验证
✅ 类型安全
✅ 错误处理

✅ 减少样板代码
✅ 自动序列化
✅ IDE支持

✅ 代码简洁
✅ 易于维护
✅ 可读性强

✅ 接口规范
✅ 文档生成
✅ 类型提示

6.2 小E项目应用总结

应用场景:

  1. ✅ AI出题的结构化输出
  2. ✅ AI审题的质量评估
  3. ✅ AI阅题的批阅结果
  4. ✅ 学情报告的数据结构
  5. ✅ 知识图谱的节点定义

核心优势:

  • 数据格式统一,易于处理
  • 自动验证,减少错误
  • 类型安全,提高开发效率
  • 代码简洁,易于维护

6.3 学习建议

入门:

  1. 学习Pydantic基础语法
  2. 理解数据验证原理
  3. 掌握常用Field类型

进阶:

  1. 自定义验证器
  2. 嵌套模型设计
  3. 与LangChain集成

高级:

  1. 性能优化
  2. 复杂业务场景
  3. 多Agent协作

Pydantic是Agent开发中不可或缺的工具,掌握它将大大提升你的开发效率和代码质量!🚀

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐