跳过内容

递归模式实现指南

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

动机

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

定义一个递归模式

以下是如何定义一个递归的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. Query Planning with Dependencies 2. Knowledge Graph Generation