首页 / 资料库 / Hugging Face · 智能体课

资料库12 分钟读完Apache-2.0智能体Hugging FaceLangGraph

文档分析图

译自《文档分析图》 · 查看英文原文

原文出处Hugging Face Agents Course · units/zh-CN/unit2/langgraph/document_analysis_agent.mdx 原作者:Hugging Face · 许可证:Apache-2.0 License 本篇为课程官方中文译文(Hugging Face 社区翻译),诸葛AI学院仅做格式整理(去除图片与交互组件),版权归原作者所有。

文档分析图

Alfred 为您服务。作为韦恩先生值得信赖的管家,我已记录下协助处理各类文档需求的工作流程。当 Mr Wayne 外出进行...夜间活动时,我会确保所有文件、训练计划和营养方案都得到妥善分析和整理。

在离开前,他留下了本周训练计划的笔记。我随后负责拟定了明日餐点的菜单

为应对未来的类似需求,让我们使用 LangGraph 构建一个文档分析系统来服务 Mr Wayne。该系统能够:

  1. 处理图像文档
  2. 使用视觉模型 (Vision Language Model) 提取文本
  3. 在需要时执行计算(用于演示常规工具)
  4. 分析内容并提供简明摘要
  5. 执行与文档相关的特定指令

管家的工作流程

我们将构建的工作流程遵循以下结构化方案:

您可以在 这个 notebook 中查看代码,并通过 Google Colab 运行。

设置环境

python %pip install langgraph langchain_openai Pillow base64 langchain_core and imports : python import base64 from typing import List, TypedDict, Annotated, Optional from langchain.schema import HumanMessage from langchain_openai import ChatOpenAI from langchain_core.messages import AnyMessage, SystemMessage from langgraph.graph.message import add_messages from langgraph.graph import START, StateGraph from langgraph.prebuilt import tools_condition from langgraph.prebuilt import ToolNode from IPython.display import Image, display

定义智能体的状态

这个状态比我们之前见过的稍微复杂些。 AnyMessage 是来自 langchain 的类,用于定义消息,而 add_messages 是一个操作符,它会添加最新消息而不是覆盖现有状态。

这是 langGraph 中的一个新概念,您可以在状态中添加 operators 来定义它们之间的交互方式。

python class AgentState(TypedDict): # 提供的文件 input_file: Optional[str] # Contains file path (PDF/PNG) messages: Annotated[list[AnyMessage], add_messages]

准备工具

```python vision_llm = ChatOpenAI(model="gpt-4o")

def extract_text(img_path: str) -> str: """ Extract text from an image file using a multimodal model.

Master Wayne often leaves notes with his training regimen or meal plans.
This allows me to properly analyze the contents.
"""
all_text = ""
try:
    # 读取图像并编码为 base64
    with open(img_path, "rb") as image_file:
        image_bytes = image_file.read()

    image_base64 = base64.b64encode(image_bytes).decode("utf-8")

    # 准备包含 base64 图像数据的提示
    message = [
        HumanMessage(
            content=[
                {
                    "type": "text",
                    "text": (
                        "Extract all the text from this image. "
                        "Return only the extracted text, no explanations."
                    ),
                },
                {
                    "type": "image_url",
                    "image_url": {
                        "url": f"data:image/png;base64,{image_base64}"
                    },
                },
            ]
        )
    ]

    # 调用具有视觉功能的模型
    response = vision_llm.invoke(message)

    # 附加提取的文本
    all_text += response.content + "\n\n"

    return all_text.strip()
except Exception as e:
    # 管家应优雅地处理错误
    error_msg = f"Error extracting text: {str(e)}"
    print(error_msg)
    return ""

def divide(a: int, b: int) -> float: """Divide a and b - for Master Wayne's occasional calculations.""" return a / b

为管家配备工具

tools = [ divide, extract_text ]

llm = ChatOpenAI(model="gpt-4o") llm_with_tools = llm.bind_tools(tools, parallel_tool_calls=False) ```

节点

```python def assistant(state: AgentState): # 系统消息 textual_description_of_tool=""" extract_text(img_path: str) -> str: Extract text from an image file using a multimodal model.

Args:
    img_path: A local image file path (strings).

Returns:
    A single string containing the concatenated text extracted from each image.

divide(a: int, b: int) -> float: Divide a and b """ image=state["input_file"] sys_msg = SystemMessage(content=f"You are an helpful butler named Alfred that serves Mr. Wayne and Batman. You can analyse documents and run computations with provided tools:\n{textual_description_of_tool} \n You have access to some optional images. Currently the loaded image is: {image}")

return {
    "messages": [llm_with_tools.invoke([sys_msg] + state["messages"])],
    "input_file": state["input_file"]
}

```

ReAct 模式:我如何协助 Wayne 先生

请允许我解释该智能体的工作方式。该智能体遵循被称为 ReAct 的模式(推理-行动-观察)

  1. 推理 分析文档和请求内容
  2. 行动 通过调用合适的工具执行操作
  3. 观察 工具执行结果
  4. 重复 上述步骤直到完全满足需求

这是使用 langGraph 实现的简单智能体实现。

```python

The graph

builder = StateGraph(AgentState)

定义节点:这些节点完成工作

builder.add_node("assistant", assistant) builder.add_node("tools", ToolNode(tools))

定义边:这些决定了控制流如何移动

builder.add_edge(START, "assistant") builder.add_conditional_edges( "assistant", # 如果最新消息需要工具,则路由至工具 # 否则,请直接回复 tools_condition, ) builder.add_edge("tools", "assistant") react_graph = builder.compile()

展现管家的思考过程

display(Image(react_graph.get_graph(xray=True).draw_mermaid_png())) ```

管家实战示例

示例1:简单计算

在以下示例中,我们添加这个 divide 示例仅作为演示用途。

python messages = [HumanMessage(content="Divide 6790 by 5")] messages = react_graph.invoke({"messages": messages, "input_file": None})

对话将会继续:

``` Human: Divide 6790 by 5

AI Tool Call: divide(a=6790, b=5)

Tool Response: 1358.0

Alfred: The result of dividing 6790 by 5 is 1358.0. ```

示例 2:分析 Wayne 大师的训练文档

当 Wayne 大师留下他的训练和​​用餐笔记时:

python messages = [HumanMessage(content="According to the note provided by Mr. Wayne in the provided images. What's the list of items I should buy for the dinner menu?")] messages = react_graph.invoke({"messages": messages, "input_file": "Batman_training_and_meals.png"})

交互将进行:

``` 用户:根据 Wayne 先生在提供的图像中的注释。我应该为晚餐菜单购买哪些物品?

AI Tool Call: extract_text(img_path="Batman_training_and_meals.png")

Tool Response: [包含训练计划和菜单详情的提取文本]

Alfred:根据晚餐菜单,您应该购买以下物品:

  1. 草饲本地西冷牛排(Grass-fed local sirloin steak)
  2. 有机菠菜(Organic spinach)
  3. 皮克略辣椒(Piquillo peppers)
  4. 土豆(用于烤制金黄香草土豆)
  5. 鱼油(2 克)

确保牛排是草饲的,并且菠菜和辣椒是有机的,以获得最佳品质的餐点。 ```

关键要点

若您希望创建自己的文档分析管家,请遵循以下关键原则:

  1. 定义清晰的工具(Define clear tools)用于特定文档相关任务
  2. 创建强大的状态跟踪器(Create a robust state tracker)以保持工具调用之间的上下文
  3. 考虑错误处理机制(Consider error handling)应对工具调用失败
  4. 保持上下文感知能力(Maintain contextual awareness)通过 add_messages 操作符确保历史交互的连贯性

遵循这些原则,您也能提供符合韦恩庄园标准的卓越文档分析服务。

相信以上解释已足够详尽。恕我失陪,韦恩老爷的披风还需在夜巡前熨烫妥当。

这篇在讲什么,跟咱们的课怎么对?

资料库是大厂公开教材的中文译本,偏原理和工程做法。想看面向中小企业的白话版本,去入门课场景课