跳到内容

规划和执行查询计划

本示例演示了如何在问答系统中使用 OpenAI 函数调用 ChatCompletion 模型来规划和执行查询计划。通过使用列表将复杂问题分解为具有明确依赖关系的小子问题,系统可以系统地收集必要信息来回答主要问题,类似于知识图谱提取

动机

本示例的目标是展示如何使用查询规划来处理复杂问题、促进迭代信息收集、自动化工作流程和优化流程。通过利用 OpenAI 函数调用模型,您可以设计和执行结构化计划以有效地找到答案。

用例

  • 复杂问题解答
  • 迭代信息收集
  • 工作流程自动化
  • 流程优化

借助 OpenAI 函数调用模型,您可以定制规划过程并将其集成到您的特定应用程序中,以满足您的独特需求。

定义结构

让我们定义必要的 Pydantic 模型来表示查询计划和查询。

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


class Query(BaseModel):
    """Class representing a single question in a query plan."""

    id: int = Field(..., description="Unique id of the query")
    question: str = Field(
        ...,
        description="Question asked using a question answering system",
    )
    dependencies: List[int] = Field(
        default_factory=list,
        description="List of sub questions that need to be answered before asking this question",
    )
    node_type: Literal["SINGLE", "MERGE_MULTIPLE_RESPONSES"] = Field(
        default="SINGLE",
        description="Type of question, either a single question or a multi-question merge",
    )


class QueryPlan(BaseModel):
    """Container class representing a tree of questions to ask a question answering system."""

    query_graph: List[Query] = Field(
        ..., description="The query graph representing the plan"
    )

    def _dependencies(self, ids: List[int]) -> List[Query]:
        """Returns the dependencies of a query given their ids."""
        return [q for q in self.query_graph if q.id in ids]

图生成

请注意,本示例生成的是一个具有依赖关系的扁平列表,它类似于图;虽然 pydantic 允许递归定义,但对于模型来说,生成扁平模式比递归模式更容易且不易混淆。如果您想查看递归示例,请参阅递归模式

规划查询计划

现在,让我们演示如何使用定义的模型和 OpenAI API 来规划和执行查询计划。

import instructor
from openai import OpenAI


# Apply the patch to the OpenAI client
# enables response_model keyword
client = instructor.from_openai(OpenAI())


def query_planner(question: str) -> QueryPlan:
    PLANNING_MODEL = "gpt-4o-mini"

    messages = [
        {
            "role": "system",
            "content": "You are a world class query planning algorithm capable ofbreaking apart questions into its dependency queries such that the answers can be used to inform the parent question. Do not answer the questions, simply provide a correct compute graph with good specific questions to ask and relevant dependencies. Before you call the function, think step-by-step to get a better understanding of the problem.",
        },
        {
            "role": "user",
            "content": f"Consider: {question}\nGenerate the correct query plan.",
        },
    ]

    root = client.chat.completions.create(
        model=PLANNING_MODEL,
        temperature=0,
        response_model=QueryPlan,
        messages=messages,
        max_tokens=1000,
    )
    return root
plan = query_planner(
    "What is the difference in populations of Canada and the Jason's home country?"
)
plan.model_dump()

无 RAG

虽然我们在本示例中构建了查询计划,但我们并未提出实际回答问题的方法。您可以实现自己的答案函数,该函数可能会进行检索并调用 openai 进行检索增强生成。该步骤也会使用函数调用,但这超出了本示例的范围。

{
    "query_graph": [
        {
            "dependencies": [],
            "id": 1,
            "node_type": "SINGLE",
            "question": "Identify Jason's home country",
        },
        {
            "dependencies": [],
            "id": 2,
            "node_type": "SINGLE",
            "question": "Find the population of Canada",
        },
        {
            "dependencies": [1],
            "id": 3,
            "node_type": "SINGLE",
            "question": "Find the population of Jason's home country",
        },
        {
            "dependencies": [2, 3],
            "id": 4,
            "node_type": "SINGLE",
            "question": "Calculate the difference in populations between Canada and Jasons home country",
        },
    ]
}

在上面的代码中,我们定义了一个 query_planner 函数,它接受一个问题作为输入,并使用 OpenAI API 生成一个查询计划。

结论

在本示例中,我们演示了如何使用 OpenAI 函数调用 ChatCompletion 模型在问答系统中使用规划查询。我们使用 Pydantic 定义了必要的结构,并创建了一个查询规划函数,该函数为回答复杂问题生成结构化计划。

查询规划器将主要问题分解为更小、更易管理的子问题,并建立它们之间的依赖关系。这种方法提供了一种系统化和组织化的方式来处理多步查询。

对于此概念的更高级实现和变体,您可以探索

  1. 查询规划和执行示例
  2. 使用拓扑排序进行任务规划

这些示例提供了关于如何利用结构化输出进行复杂查询规划和任务管理的更多见解。

请根据您的特定用例随意调整此代码,并探索在您的应用程序中使用 OpenAI 函数调用来规划和构建复杂工作流程的可能性。