跳到内容

递归模式实现指南

本指南演示了如何在 Instructor 中使用 Pydantic 模型处理递归模式。虽然扁平模式通常更容易处理,但某些用例需要递归结构来有效地表示分层数据。

动机

在处理以下情况时,递归模式特别有用: * 嵌套的组织结构 * 文件系统层次结构 * 带有回复的评论串 * 带有子任务的任务依赖 * 抽象语法树

定义递归模式

这是一个如何定义递归 Pydantic 模型的示例

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


class RecursiveNode(BaseModel):
    """A node that can contain child nodes of the same type."""

    name: str = Field(..., description="Name of the node")
    value: Optional[str] = Field(
        None, description="Optional value associated with the node"
    )
    children: List["RecursiveNode"] = Field(
        default_factory=list, description="List of child nodes"
    )


# Required for recursive Pydantic models
RecursiveNode.model_rebuild()

示例用法

让我们看看如何在 Instructor 中使用此递归模式

import instructor
from openai import OpenAI

client = instructor.from_openai(OpenAI())


def parse_hierarchy(text: str) -> RecursiveNode:
    """Parse text into a hierarchical structure."""
    return client.chat.completions.create(
        model="gpt-4",
        messages=[
            {
                "role": "system",
                "content": "You are an expert at parsing text into hierarchical structures.",
            },
            {
                "role": "user",
                "content": f"Parse this text into a hierarchical structure: {text}",
            },
        ],
        response_model=RecursiveNode,
    )


# Example usage
hierarchy = parse_hierarchy(
    """
Company: Acme Corp
- Department: Engineering
  - Team: Frontend
    - Project: Website Redesign
    - Project: Mobile App
  - Team: Backend
    - Project: API v2
    - Project: Database Migration
- Department: Marketing
  - Team: Digital
    - Project: Social Media Campaign
  - Team: Brand
    - Project: Logo Refresh
"""
)

验证和最佳实践

在使用递归模式时

  1. 定义模型后始终调用 model_rebuild()
  2. 考虑添加最大深度验证以防止无限递归
  3. 正确使用类型提示以保持代码清晰
  4. 考虑为特定的业务规则实现自定义验证器
from pydantic import model_validator


class RecursiveNodeWithDepth(RecursiveNode):
    @model_validator(mode='after')
    def validate_depth(self) -> "RecursiveNodeWithDepth":
        def check_depth(node: "RecursiveNodeWithDepth", current_depth: int = 0) -> int:
            if current_depth > 10:  # Maximum allowed depth
                raise ValueError("Maximum depth exceeded")
            return max(
                [check_depth(child, current_depth + 1) for child in node.children],
                default=current_depth,
            )

        check_depth(self)
        return self

性能注意事项

虽然递归模式功能强大,但语言模型正确处理它们可能更具挑战性。请考虑以下技巧

  1. 结构尽量保持扁平
  2. 使用清晰的命名规范
  3. 在提示中提供好的示例
  4. 考虑将非常大的结构分解成更小的块

结论

递归模式为应用程序中处理分层数据结构提供了一种强大的方法。虽然它们比扁平模式需要更仔细的处理,但对于某些用例来说,它们是无价的。

有关处理复杂数据结构的更多示例,请查看: 1. 带有依赖关系的查询规划 2. 知识图谱生成