langgraph入门教案

LangGraph 深度学习教案

目录

  1. 引言
    • LangChain 与 LangGraph 的关系
    • 为什么选择 LangGraph
  2. LangGraph 基础概念
    • 节点(Nodes)
    • 边(Edges)
    • 状态(State)
  3. 环境配置
    • 安装必要的库
    • 配置数据库和模型
  4. 构建单代理工作流程
    • 定义 SQL 执行工具
    • 定义代理状态
    • 构建代理
    • 可视化代理图
    • 测试代理
  5. 持久化和流式处理
    • 持久化状态
    • 流式处理数据
    • 多线程交互
  6. 构建多代理系统
    • 定义多代理状态
    • 构建路由器节点
    • 构建专家节点
    • 构建编辑器和人类反馈节点
    • 测试多代理系统
  7. 总结

1. 引言

LangChain 与 LangGraph 的关系

LangChain 是一个用于构建由大型语言模型(LLM)驱动的应用程序的领先框架。它允许开发者使用 LangChain 表达语言(LCEL)来定义和执行操作序列,这些序列被称为(Chains)。这些链可以视为有向无环图(DAG),用于线性执行任务。

然而,随着 LLM 应用程序的发展,特别是在构建代理(Agents)时,我们需要更复杂的交互,包括循环、条件逻辑和多步骤推理。这就引入了 LangGraph,它是 LangChain 的一个新模块,允许我们将交互建模为循环图,从而支持更复杂的工作流和代理行为。

为什么选择 LangGraph

LangGraph 提供了以下优势:

  • 灵活性:支持循环和条件逻辑,能够构建复杂的对话和推理流程。
  • 模块化设计:通过节点和边的组合,可以轻松地添加或修改代理的行为。
  • 持久化和恢复:状态在每个步骤后自动保存,允许在任何时刻暂停和恢复执行,这对于需要人机交互的应用程序非常重要。

2. LangGraph 基础概念

在开始实际编码之前,我们需要理解 LangGraph 的三个核心概念:节点、边和状态。

节点(Nodes)

节点代表实际的操作,可以是以下之一:

  • LLM 调用:调用大型语言模型进行推理或生成文本。
  • 代理:可以是另一个嵌套的代理,负责特定任务。
  • 函数或工具:执行特定的功能,如数据库查询、API 调用等。

边(Edges)

连接节点,确定图的执行流程。边有两种类型:

  • 基本边:简单地将一个节点连接到下一个节点,表示顺序执行。
  • 条件边:包含条件逻辑,根据状态决定下一步执行哪个节点。

状态(State)

状态是图的快照,包含执行过程中所有需要共享或持久化的数据。状态在节点之间传递,并可以被节点读取或修改。状态的设计对于代理的正确执行至关重要,因为它允许节点之间共享信息,并支持复杂的交互。


3. 环境配置

在开始编写代码之前,我们需要设置开发环境,安装必要的库,并配置模型和数据库。

安装必要的库

确保您的计算机上安装了 Python 3.6 或更高版本。

# 安装 langchain_community
pip install langchain_community

# 更新安装 langgraph
pip install -U langgraph

# 安装 graphviz(用于绘制图形)
brew install graphviz  # 如果您使用的是 macOS

# 安装 pygraphviz(用于在 Python 中使用 graphviz)
pip install pygraphviz

注意:在安装 pygraphviz 时,可能需要指定编译选项,以正确找到 graphviz 的头文件和库文件。如果遇到安装问题,请参考 pygraphviz 的安装指南

配置数据库和模型

在本教案中,我们将使用 ClickHouse 数据库和 OpenAI 的 GPT-4 模型(或其替代模型)。

import os
import json

# 读取配置文件(假设您有一个包含 API 密钥的 config.json 文件)
with open('config.json') as f:
    config = json.loads(f.read())

# 设置环境变量
os.environ["OPENAI_MODEL_NAME"] = 'gpt-4o-mini'  # 或者您选择的模型
os.environ["OPENAI_API_KEY"] = config['OPENAI_API_KEY']
os.environ["TAVILY_API_KEY"] = config["TAVILY_API_KEY"]

4. 构建单代理工作流程

在这一部分中,我们将构建一个简单的代理,能够根据用户输入执行 SQL 查询,并返回结果。

4.1 定义 SQL 执行工具

首先,我们需要定义一个工具,用于执行 SQL 查询。

from langchain_core.tools import tool
from pydantic.v1 import BaseModel, Field

# 定义 SQL 查询的参数模型
class SQLQuery(BaseModel):
    query: str = Field(description="要执行的 SQL 查询")

# 定义执行 SQL 的工具
@tool(args_schema=SQLQuery)
def execute_sql(query: str) -> str:
    """返回 SQL 查询执行的结果"""
    return get_clickhouse_data(query)

我们还需要定义 get_clickhouse_data 函数,用于实际执行 SQL 查询。

CH_HOST = 'http://localhost:8123'  # ClickHouse 默认地址
import requests

def get_clickhouse_data(query, host=CH_HOST, connection_timeout=1500):
    r = requests.post(host, params={'query': query}, timeout=connection_timeout)
    if r.status_code == 200:
        return r.text
    else:
        return '数据库返回以下错误:\n' + r.text

说明

  • 我们使用 @tool 装饰器将 execute_sql 函数注册为 LangChain 工具。
  • SQLQuery 是一个 Pydantic 模型,用于定义工具的参数和描述,帮助 LLM 正确地调用工具。
  • execute_sql 函数调用了 get_clickhouse_data 来执行实际的 SQL 查询。

4.2 定义代理状态

接下来,我们需要定义代理的状态,以便在节点之间共享信息。

from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
from langchain_core.messages import AnyMessage, SystemMessage, HumanMessage, ToolMessage

# 定义代理状态
class AgentState(TypedDict):
    messages: Annotated[list[AnyMessage], operator.add]

说明

  • AgentState 是一个字典类型,包含一个 messages 列表,用于存储对话历史。
  • Annotatedoperator.add 用于指示在状态更新时,新的消息将添加到列表中,而不是替换。

4.3 构建代理

现在,我们开始构建代理,定义其节点和执行逻辑。

class SQLAgent:
    def __init__(self, model, tools, system_prompt=""):
        self.system_prompt = system_prompt
        graph = StateGraph(AgentState)

        # 添加节点
        graph.add_node("llm", self.call_llm)
        graph.add_node("function", self.execute_function)

        # 添加条件边:如果存在函数调用,则执行函数节点,否则结束
        graph.add_conditional_edges(
            "llm",
            self.exists_function_calling,
            {True: "function", False: END}
        )

        # 添加边:从函数节点回到 llm 节点
        graph.add_edge("function", "llm")

        # 设置起点
        graph.set_entry_point("llm")

        # 编译图
        self.graph = graph.compile()
        self.tools = {t.name: t for t in tools}
        self.model = model.bind_tools(tools)

    # 检查是否存在函数调用
    def exists_function_calling(self, state: AgentState):
        result = state['messages'][-1]
        return len(result.tool_calls) > 0

    # 调用 LLM
    def call_llm(self, state: AgentState):
        messages = state['messages']
        if self.system_prompt:
            messages = [SystemMessage(content=self.system_prompt)] + messages
        message = self.model.invoke(messages)
        return {'messages': [message]}

    # 执行函数调用
    def execute_function(self, state: AgentState):
        tool_calls = state['messages'][-1].tool_calls
        results = []
        for t in tool_calls:
            if not t['name'] in self.tools:
                result = "错误:没有这样的工具,请重试"
            else:
                result = self.tools[t['name']].invoke(t['args'])
            results.append(ToolMessage(tool_call_id=t['id'], name=t['name'], content=str(result)))
        return {'messages': results}

说明

  • 初始化:我们创建了一个 StateGraph,添加了两个节点 llmfunction,以及条件边和普通边。
  • 节点函数
    • call_llm:调用 LLM 模型,根据消息历史生成回复。
    • execute_function:执行 LLM 请求的函数调用(工具),并将结果返回给 LLM。
  • 条件边函数
    • exists_function_calling:检查 LLM 的回复中是否包含函数调用,决定下一个节点。

4.4 可视化代理图

为了更好地理解代理的结构,我们可以可视化代理的图形。

from IPython.display import Image

# 实例化代理
prompt = '''您是 SQL 和数据分析方面的高级专家...
您的目标是为数据库中的表提供详细的文档,以帮助用户。'''
model = ChatOpenAI(model="gpt-4o-mini")
doc_agent = SQLAgent(model, [execute_sql], system_prompt=prompt)

# 可视化图形
Image(doc_agent.graph.get_graph().draw_png())

说明

  • 使用 pygraphviz 库来绘制图形。
  • 图形显示了节点和边的连接关系,便于理解代理的执行流程。

4.5 测试代理

现在,我们可以测试代理,看看它如何响应用户的请求。

# 发送用户消息
messages = [HumanMessage(content="我们在 ecommerce_db.users 表中有什么信息?")]
result = doc_agent.graph.invoke({"messages": messages})

# 打印代理的回复
print(result['messages'][-1].content)

预期输出

代理应该通过调用 execute_sql 工具,查询数据库表的结构,并返回表的列名和数据类型。


5. 持久化和流式处理

在实际应用中,代理需要能够处理长时间的对话,并在多个步骤之间保持状态。这就需要持久化和流式处理。

5.1 持久化状态

我们可以使用 SQLite 数据库来持久化代理的状态。

from langgraph.checkpoint.sqlite import SqliteSaver

# 使用内存中的 SQLite 数据库进行持久化
memory = SqliteSaver.from_conn_string(":memory:")

说明

  • 我们创建了一个内存中的 SQLite 数据库,可以替换为实际的文件路径来持久化状态。

5.2 流式处理数据

为了支持长对话和实时响应,我们可以使用流式处理。

# 使用预构建的 ReAct 代理
from langgraph.prebuilt import create_react_agent

prebuilt_doc_agent = create_react_agent(model, [execute_sql], checkpointer=memory)

# 定义线程 ID
thread = {"configurable": {"thread_id": "1"}}
messages = [HumanMessage(content="我们在 ecommerce_db.users 表中有什么信息?")]

# 流式处理
for event in prebuilt_doc_agent.stream({"messages": messages}, thread):
    for v in event.values():
        v['messages'][-1].pretty_print()

说明

  • stream 方法允许我们逐步获取代理的响应,包括中间步骤,如工具调用。
  • thread 参数用于标识对话线程,支持多线程交互。

5.3 多线程交互

我们可以在同一线程中发送后续消息,代理会保持对话上下文。

# 继续在同一线程中发送后续消息
followup_messages = [HumanMessage(content="我想知道列名和类型。也许你可以使用 DESCRIBE 在数据库中查看。")]

for event in prebuilt_doc_agent.stream({"messages": followup_messages}, thread):
    for v in event.values():
        v['messages'][-1].pretty_print()

说明

  • 代理会根据之前的对话历史,理解用户的意图,并做出适当的响应。

6. 构建多代理系统

在更复杂的应用场景中,我们可能需要多个代理协同工作,根据不同的用户请求,选择合适的代理来处理。这需要构建一个多代理系统。

6.1 定义多代理状态

首先,定义一个更复杂的状态,用于在多个代理之间传递信息。

class MultiAgentState(TypedDict):
    question: str
    question_type: str
    answer: str
    feedback: str

说明

  • question:用户的问题。
  • question_type:问题的类型,用于路由到不同的代理。
  • answer:代理的回答。
  • feedback:用户的反馈。

6.2 构建路由器节点

路由器节点的作用是根据用户的问题,确定应该由哪个代理来处理。

def router_node(state: MultiAgentState):
    question_category_prompt = '''您是分析支持的高级专家。您的任务是对收到的问题进行分类。
根据您的回答,问题将被路由到正确的团队,所以您的任务对我们团队至关重要。
有 3 种可能的问题类型:
- DATABASE:与数据库(表或字段)相关的问题
- LANGCHAIN:与 LangGraph 或 LangChain 库相关的问题
- GENERAL:一般性问题
请仅返回一个单词(DATABASE、LANGCHAIN 或 GENERAL)。'''
    messages = [
        SystemMessage(content=question_category_prompt),
        HumanMessage(content=state['question'])
    ]
    model = ChatOpenAI(model="gpt-4o-mini")
    response = model.invoke(messages)
    return {"question_type": response.content.strip().upper()}

说明

  • 路由器使用 LLM 来分类问题类型。
  • 返回的 question_type 将用于决定下一个执行的节点。

6.3 构建专家节点

根据不同的问题类型,我们需要构建不同的专家节点。

SQL 专家节点
def sql_expert_node(state: MultiAgentState):
    sql_expert_system_prompt = '''
    您是 SQL 方面的专家,可以帮助团队收集所需的数据以支持他们的决策。
    您非常准确,并考虑到数据中的所有细微差别。
    您使用 SQL 来获取数据,然后回答问题。
    '''
    model = ChatOpenAI(model="gpt-4o-mini")
    sql_agent = create_react_agent(model, [execute_sql], state_modifier=sql_expert_system_prompt)
    messages = [HumanMessage(content=state['question'])]
    result = sql_agent.invoke({"messages": messages})
    return {'answer': result['messages'][-1].content}
搜索专家节点
from langchain_community.tools.tavily_search import TavilySearchResults

tavily_tool = TavilySearchResults(max_results=5)

def search_expert_node(state: MultiAgentState):
    search_expert_system_prompt = '''
    您是 LangChain 和相关技术的专家。
    您的目标是根据搜索提供的结果回答问题。
    您不添加任何自己的信息,仅提供基于其他来源的信息。
    '''
    model = ChatOpenAI(model="gpt-4o-mini")
    search_agent = create_react_agent(model, [tavily_tool], state_modifier=search_expert_system_prompt)
    messages = [HumanMessage(content=state['question'])]
    result = search_agent.invoke({"messages": messages})
    return {'answer': result['messages'][-1].content}
通用助手节点
def general_assistant_node(state: MultiAgentState):
    general_prompt = '''您是一个友好的助手,目标是回答一般性问题。
    请不要提供任何未经验证的信息,如果您没有足够的信息,请直接说您不知道。
    '''
    messages = [
        SystemMessage(content=general_prompt),
        HumanMessage(content=state['question'])
    ]
    model = ChatOpenAI(model="gpt-4o-mini")
    response = model.invoke(messages)
    return {"answer": response.content}

6.4 构建编辑器和人类反馈节点

我们还可以添加一个编辑器节点,用于根据用户的反馈修改答案。

def human_feedback_node(state: MultiAgentState):
    pass  # 该节点用于等待用户反馈

def editor_node(state: MultiAgentState):
    editor_prompt = '''您是一个编辑,您的目标是根据反馈为客户提供最终答案。
您不添加任何自己的信息。您使用友好和专业的语气。
在输出中,请提供给客户的最终答案,不要添加额外的评论。
以下是您需要的所有信息:

客户的问题:
----
{question}
----
初步答案:
----
{answer}
----
反馈:
----
{feedback}
----
'''
    messages = [
        SystemMessage(content=editor_prompt.format(
            question=state['question'],
            answer=state['answer'],
            feedback=state['feedback']
        ))
    ]
    model = ChatOpenAI(model="gpt-4o-mini")
    response = model.invoke(messages)
    return {"answer": response.content}

说明

  • human_feedback_node:用于等待用户的反馈,可以在此处暂停执行。
  • editor_node:根据用户的反馈,修改答案并生成最终回复。

6.5 测试多代理系统

构建图形
builder = StateGraph(MultiAgentState)

# 添加节点
builder.add_node("router", router_node)
builder.add_node('database_expert', sql_expert_node)
builder.add_node('langchain_expert', search_expert_node)
builder.add_node('general_assistant', general_assistant_node)
builder.add_node('human', human_feedback_node)
builder.add_node('editor', editor_node)

# 添加条件边
builder.add_conditional_edges(
    "router",
    lambda state: state['question_type'],
    {'DATABASE': 'database_expert', 'LANGCHAIN': 'langchain_expert', 'GENERAL': 'general_assistant'}
)

# 设置起点
builder.set_entry_point("router")

# 添加边
builder.add_edge('database_expert', 'human')
builder.add_edge('langchain_expert', 'human')
builder.add_edge('general_assistant', 'human')
builder.add_edge('human', 'editor')
builder.add_edge('editor', END)

# 编译图形,设置在 human 节点前中断
graph = builder.compile(checkpointer=memory, interrupt_before=['human'])
测试代理
thread = {"configurable": {"thread_id": "2"}}

# 发送初始问题
for event in graph.stream({'question': "ecommerce_db.users 表中的字段类型是什么?"}, thread):
    print(event)

# 获取用户反馈
user_input = input("是否需要修改答案?")
graph.update_state(thread, {"feedback": user_input}, as_node="human")

# 继续执行
for event in graph.stream(None, thread, stream_mode="values"):
    print(event['answer'])

说明

  • 执行流程在 human 节点前暂停,等待用户的反馈。
  • 用户提供反馈后,代理继续执行,editor 节点生成最终的答案。

7. 总结

在本教案中,我们深入学习了 LangGraph 的使用方法,包括:

  • 构建单代理工作流程:创建一个能够执行 SQL 查询的代理,理解节点、边和状态的基本概念。
  • 持久化和流式处理:实现代理状态的持久化,支持长对话和多线程交互。
  • 构建多代理系统:创建一个包含路由器、专家和编辑器的复杂系统,能够根据问题类型自动选择合适的代理进行回答,并引入人机交互以提高答案质量。

关键要点

  • LangGraph 提供了强大的工具来构建复杂的代理系统,支持循环、条件逻辑和多步骤推理。
  • 状态管理对于代理的执行至关重要,正确地设计和维护状态,可以实现丰富的交互和持久化。
  • 人机交互能够提高系统的可靠性和用户满意度,在关键步骤引入用户反馈,确保最终的答案符合用户期望。

通过本次学习,您应该能够:

  • 理解 LangGraph 的核心概念和优势。
  • 使用 LangGraph 构建复杂的对话代理系统。
  • 在实际项目中应用 LangGraph,提升 LLM 应用程序的灵活性和可扩展性。

希望本教案对您的学习有所帮助!如有任何疑问,建议您查阅 LangGraph 的官方文档,或尝试在实践中应用这些概念,以加深理解。

Swarm 框架入门教案

目录

  1. 引言
    • 什么是 Swarm?
    • 为什么选择 Swarm?
  2. 安装与环境配置
    • 系统要求
    • 安装 Swarm
  3. Swarm 的基本概念
    • Swarm 客户端
    • Agent(代理)
    • 交接(Handoffs)
  4. Swarm 的基本使用方法
    • 创建 Swarm 客户端
    • 定义 Agent
    • 运行 Swarm
  5. Agent 的深入理解
    • Agent 的属性和字段
    • 指令(Instructions)
    • 功能(Functions)
    • 交接与上下文变量更新
  6. 运行 Swarm 的参数和响应
    • client.run() 的参数详解
    • Response 对象的结构
  7. 高级主题
    • 函数模式与类型提示
    • 上下文变量的使用
    • 流式传输(Streaming)
  8. Swarm 的优势与应用场景
    • 轻量级和可扩展性
    • 高度可定制的设计模式
    • 适用场景
  9. 总结

1. 引言

什么是 Swarm?

Swarm 是 OpenAI 于 2024 年 10 月 12 日开源的一个实验性质的多智能体编排框架。它的核心目标是让智能体(Agents)之间的协调和执行变得更加轻量级、易于控制和测试。Swarm 提供了一种简化的方式来创建和管理多个 AI 代理,允许它们之间进行高效的通信和任务协作。

为什么选择 Swarm?

  • 轻量级:Swarm 几乎完全在客户端运行,不需要复杂的服务器设置。
  • 可扩展性:能够处理大量独立的功能和指令,适用于构建复杂的多代理系统。
  • 高可控性:提供了对代理和函数执行的精细控制,方便测试和调试。
  • 易于使用:提供了简洁的 API,使开发者可以快速上手。

2. 安装与环境配置

系统要求

  • Python 版本:需要 Python 3.10 或更高版本。

安装 Swarm

在命令行中执行以下命令安装 Swarm:

pip install git+https://github.com/openai/swarm.git

3. Swarm 的基本概念

Swarm 客户端

Swarm 客户端是与 Swarm 框架交互的主要接口。它类似于 OpenAI 的 ChatCompletion API,可以接受消息并返回响应。

Agent(代理)

Agent 是 Swarm 的核心抽象,代表了具有特定指令和功能的独立实体。每个 Agent 包含:

  • Instructions(指令):定义 Agent 的行为方式。
  • Functions(功能):Agent 可以调用的 Python 函数,用于执行特定任务。

交接(Handoffs)

Agent 可以在对话过程中将执行权交接给另一个 Agent。这允许在多个 Agent 之间进行任务协作,实现复杂的工作流程。


4. Swarm 的基本使用方法

创建 Swarm 客户端

首先,导入 Swarm 并创建一个客户端实例:

from swarm import Swarm

client = Swarm()

定义 Agent

创建两个 Agent,分别具有不同的指令和功能:

from swarm import Agent

def transfer_to_agent_b():
    return agent_b  # 将执行权交接给 Agent B

agent_a = Agent(
    name="Agent A",
    instructions="You are a helpful agent.",
    functions=[transfer_to_agent_b],
)

agent_b = Agent(
    name="Agent B",
    instructions="Only speak in Haikus.",
)

运行 Swarm

使用 client.run() 方法来运行 Agent,并传入初始消息:

response = client.run(
    agent=agent_a,
    messages=[{"role": "user", "content": "I want to talk to agent B."}],
)

print(response.messages[-1]["content"])

预期输出

An example haiku
From Agent B to you now
Hope you enjoy it

5. Agent 的深入理解

Agent 的属性和字段

  • name:Agent 的名称。
  • instructions:Agent 的指令,定义其行为。
  • functions:Agent 可以调用的函数列表。
  • model:Agent 使用的模型(默认为 “gpt-4o”)。

指令(Instructions)

Agent 的指令可以是字符串,也可以是返回字符串的函数。这些指令会作为系统提示,指导 Agent 的行为。

示例

agent = Agent(
    instructions="You are a helpful assistant."
)

或者使用函数动态生成指令:

def dynamic_instructions(context_variables):
    user_name = context_variables.get("user_name", "User")
    return f"Help {user_name} with their requests."

agent = Agent(
    instructions=dynamic_instructions
)

功能(Functions)

Agent 可以调用 Python 函数来执行特定任务。这些函数可以访问上下文变量,并返回值或交接给另一个 Agent。

示例

def greet(context_variables, language):
    user_name = context_variables.get("user_name", "User")
    greeting = "Hola" if language.lower() == "spanish" else "Hello"
    print(f"{greeting}, {user_name}!")
    return "Done"

agent = Agent(
    functions=[greet]
)

交接与上下文变量更新

Agent 可以通过函数返回另一个 Agent 来实现交接,还可以更新上下文变量。

示例

from swarm import Result

sales_agent = Agent(name="Sales Agent")

def transfer_to_sales():
    return Result(
        agent=sales_agent,
        context_variables={"department": "sales"}
    )

agent = Agent(
    functions=[transfer_to_sales]
)

6. 运行 Swarm 的参数和响应

client.run() 的参数详解

  • agent(必需):初始运行的 Agent。
  • messages(必需):消息列表,与 OpenAI 的 Chat Completion API 格式相同。
  • context_variables:可选的上下文变量字典,供函数和 Agent 指令使用。
  • max_turns:允许的最大对话轮数。
  • model_override:覆盖 Agent 使用的模型。
  • execute_tools:是否执行工具(函数),默认为 True。
  • stream:是否启用流式响应。
  • debug:是否启用调试日志。

Response 对象的结构

  • messages:对话过程中生成的消息列表。
  • agent:处理最后一条消息的 Agent。
  • context_variables:最新的上下文变量。

示例

response = client.run(
    agent=agent_a,
    messages=[{"role": "user", "content": "Hello!"}],
    context_variables={"user_name": "Alice"}
)

print(response.messages)
print(response.agent.name)
print(response.context_variables)

7. 高级主题

函数模式与类型提示

Swarm 可以自动将函数转换为 JSON 模式,用于函数调用。支持类型提示和文档字符串。

示例

def greet(name: str, age: int, location: str = "New York"):
    """Greets the user.

    Args:
        name: Name of the user.
        age: Age of the user.
        location: Location of the user.
    """
    return f"Hello {name}, age {age}, from {location}!"

上下文变量的使用

上下文变量可以在 client.run() 时传入,供 Agent 的指令和函数使用。

示例

response = client.run(
    agent=agent,
    messages=[{"role": "user", "content": "Hi!"}],
    context_variables={"user_name": "Bob"}
)

流式传输(Streaming)

Swarm 支持流式响应,类似于 OpenAI 的 Chat Completion 流式 API。

使用方法

stream = client.run(agent, messages, stream=True)
for chunk in stream:
    print(chunk)

8. Swarm 的优势与应用场景

轻量级和可扩展性

Swarm 几乎完全在客户端运行,不需要复杂的服务器设置,非常适合快速开发和测试。

高度可定制的设计模式

通过简单的 Agent 和函数组合,可以构建复杂的多代理系统,满足各种特定需求。

适用场景

  • 多角色对话系统:如客服、销售等不同部门的交互。
  • 任务编排与工作流程管理:定义复杂的任务流,并在不同的 Agent 之间切换。
  • 教育与教学:模拟不同的教学助手,提供多样化的教学支持。

9. 总结

Swarm 框架为多智能体系统的开发提供了一个轻量级、高效且易于使用的解决方案。通过深入理解 Agent、函数和交接等核心概念,开发者可以快速构建复杂的多代理应用。

学习要点

  • 理解 Swarm 的基本架构和运行机制。
  • 学会定义 Agent 及其指令和功能。
  • 掌握上下文变量和交接的使用方法。
  • 了解 Swarm 的高级特性,如函数模式和流式传输。

下一步

  • 尝试扩展示例代码,创建更多自定义的 Agent 和函数。
  • 探索 Swarm 在您特定领域的应用,如数据处理、自动化任务等。
  • 关注 Swarm 的更新和社区,获取更多资源和支持。

附录:Swarm 官方文档和资源

  • GitHub 仓库:https://github.com/openai/swarm
  • OpenAI 官方博客:介绍 Swarm 的设计理念和应用场景
  • 示例代码和教程:探索更多 Swarm 的实际应用案例

基于本地 AI 的新闻聚合器构建教案

目录

  1. 引言
    • 项目背景与目标
    • 技术栈简介
  2. 环境设置
    • 安装必要的软件和库
    • 配置环境变量
  3. 核心组件解析
    • Ollama 与 Llama 3.2 模型
    • Swarm 代理编排框架
    • DuckDuckGo 搜索
  4. 项目实现步骤
    • 步骤一:设置环境
    • 步骤二:创建新闻搜索功能
    • 步骤三:定义 AI 代理
    • 步骤四:协调工作流程
    • 步骤五:运行系统
  5. 代码详解
    • 完整代码展示
    • 关键代码解析
  6. 项目运行与测试
    • 运行示例
    • 预期输出
  7. 扩展与优化
    • 个性化定制
    • 安全与隐私考虑
    • 可能的改进方向
  8. 总结

1. 引言

项目背景与目标

在信息爆炸的时代,及时获取感兴趣领域的最新新闻变得越来越重要。然而,面对大量的信息源,手动筛选和跟踪特定主题的新闻可能既耗时又困难。本教案的目标是引导您构建一个本地运行的个性化新闻聚合器,利用生成式 AI 和代理技术,实现自动化的新闻收集、整理和展示。

技术栈简介

为了实现上述目标,我们将使用以下技术:

  • Ollama 与 Llama 3.2 模型:Ollama 提供了在本地运行大型语言模型的能力,Llama 3.2 是一个强大的语言模型,用于自然语言处理任务。
  • Swarm 代理编排框架:Swarm 允许我们创建和管理多个 AI 代理,实现复杂的任务编排。
  • DuckDuckGo 搜索:作为一个注重隐私的搜索引擎,DuckDuckGo 提供了可靠的搜索结果,而不会跟踪用户数据。

2. 环境设置

安装必要的软件和库

首先,确保您的计算机满足以下要求:

  • 操作系统:Windows、macOS 或 Linux
  • Python 版本:3.7 或更高

安装 Ollama 并拉取 Llama 3.2 模型:

ollama pull llama3.2

安装 Python 库:

pip install git+https://github.com/openai/swarm.git duckduckgo-search

配置环境变量

设置必要的环境变量,以便 Ollama 和 Swarm 正确运行:

export OPENAI_MODEL_NAME=llama3.2
export OPENAI_BASE_URL=http://localhost:11434/v1
export OPENAI_API_KEY=any

注意:根据您的操作系统,设置环境变量的方式可能有所不同。上述命令适用于 UNIX 系统;在 Windows 上,您可以使用 set 命令。


3. 核心组件解析

Ollama 与 Llama 3.2 模型

  • Ollama:一个用于在本地运行大型语言模型的工具,支持多种模型的管理和部署。
  • Llama 3.2 模型:由 Meta AI 开发的先进语言模型,具备强大的自然语言理解和生成能力。

Swarm 代理编排框架

  • Swarm:一个用于创建和管理 AI 代理的框架,支持代理之间的通信和任务协调。
  • 代理(Agent):在 Swarm 中,代理是具有特定职责的独立实体,能够处理输入并生成输出。

DuckDuckGo 搜索

  • DuckDuckGo:一个强调用户隐私的搜索引擎,不会跟踪用户的搜索行为。
  • DuckDuckGo Search API:允许开发者通过编程方式访问搜索结果,用于集成到自定义应用中。

4. 项目实现步骤

步骤一:设置环境

  • 导入必要的库

    from duckduckgo_search import DDGS
    from swarm import Swarm, Agent
    from datetime import datetime
    
  • 初始化 Swarm 客户端和获取当前日期

    current_date = datetime.now().strftime("%Y-%m")
    client = Swarm()
    

步骤二:创建新闻搜索功能

  • 定义搜索函数

    def get_news_articles(topic):
        ddg_api = DDGS()
        results = ddg_api.text(f"{topic} {current_date}", max_results=5)
        if results:
            news_results = "\n\n".join([
                f"标题: {result['title']}\n网址: {result['href']}\n描述: {result['body']}"
                for result in results
            ])
            return news_results
        else:
            return f"未能找到关于 {topic} 的新闻结果。"
    
  • 功能说明

    • 使用 DuckDuckGo API 搜索指定主题的新闻。
    • 格式化搜索结果,提取标题、网址和描述。

步骤三:定义 AI 代理

  • 创建新闻助手代理

    news_agent = Agent(
        model="llama3.2",
        name="新闻助手",
        instructions="您提供有关给定主题的最新新闻文章,使用 DuckDuckGo 搜索。",
        functions=[get_news_articles],
    )
    
  • 创建编辑助手代理

    editor_agent = Agent(
        model="llama3.2",
        name="编辑助手",
        instructions="您审阅并最终确定新闻文章以供发布。",
    )
    
  • 代理职责

    • 新闻助手:负责获取新闻数据。
    • 编辑助手:负责审阅和精炼新闻内容。

步骤四:协调工作流程

  • 定义工作流程函数

    def run_news_workflow(topic):
        # 获取新闻
        news_response = client.run(
            agent=news_agent,
            messages=[{"role": "user", "content": f"获取关于 {topic}{current_date} 的新闻"}],
        )
        raw_news = news_response.messages[-1]["content"]
    
        # 将新闻传递给编辑助手
        edited_news_response = client.run(
            agent=editor_agent,
            messages=[{"role": "system", "content": raw_news}],
        )
        print(f"{edited_news_response.messages[-1]['content']}")
    
  • 流程说明

    1. 获取新闻:新闻助手代理接收主题,使用搜索功能获取新闻。
    2. 编辑新闻:将获取的新闻内容传递给编辑助手代理,进行审阅和精炼。
    3. 输出结果:打印最终的新闻内容。

步骤五:运行系统

  • 运行示例

    run_news_workflow("药物发现中的 AI")
    
  • 说明:调用 run_news_workflow 函数,指定感兴趣的主题,即可运行完整的新闻聚合流程。


5. 代码详解

完整代码展示

from duckduckgo_search import DDGS
from swarm import Swarm, Agent
from datetime import datetime

current_date = datetime.now().strftime("%Y-%m")

# 初始化 Swarm 客户端
client = Swarm()

# 1. 创建互联网搜索工具
def get_news_articles(topic):
    print(f"正在为 {topic} 进行 DuckDuckGo 新闻搜索...")

    # DuckDuckGo 搜索
    ddg_api = DDGS()
    results = ddg_api.text(f"{topic} {current_date}", max_results=5)
    if results:
        news_results = "\n\n".join([
            f"标题: {result['title']}\n网址: {result['href']}\n描述: {result['body']}"
            for result in results
        ])
        return news_results
    else:
        return f"未能找到关于 {topic} 的新闻结果。"

# 2. 创建 AI 代理
# 新闻助手代理
news_agent = Agent(
    model="llama3.2",
    name="新闻助手",
    instructions="您提供有关给定主题的最新新闻文章,使用 DuckDuckGo 搜索。",
    functions=[get_news_articles],
)

# 编辑助手代理
editor_agent = Agent(
    model="llama3.2",
    name="编辑助手",
    instructions="您审阅并最终确定新闻文章以供发布。",
)

# 3. 创建工作流程
def run_news_workflow(topic):
    print("运行新闻代理工作流程...")

    # 第一步: 获取新闻
    news_response = client.run(
        agent=news_agent,
        messages=[{"role": "user", "content": f"获取关于 {topic}{current_date} 的新闻"}],
    )
    raw_news = news_response.messages[-1]["content"]
    print(f"获取的新闻: {raw_news}")

    # 第二步: 将新闻传递给编辑助手
    edited_news_response = client.run(
        agent=editor_agent,
        messages=[{"role": "system", "content": raw_news}],
    )
    print(f"最终新闻内容:\n{edited_news_response.messages[-1]['content']}")

# 运行示例
run_news_workflow("药物发现中的 AI")

关键代码解析

  • get_news_articles 函数:核心的新闻搜索功能,利用 DuckDuckGo API,返回格式化的新闻结果。

  • 代理的创建

    • news_agent 包含 get_news_articles 函数,能够主动获取新闻。
    • editor_agent 不包含额外函数,主要处理传入的文本,进行编辑。
  • 工作流程的运行

    • 使用 client.run 方法,分别运行两个代理。
    • 代理之间通过消息传递,实现数据的流动和任务的衔接。

6. 项目运行与测试

运行示例

在终端或命令提示符中运行脚本:

python app.py

预期输出

运行新闻代理工作流程...
正在为 药物发现中的 AI 进行 DuckDuckGo 新闻搜索...
获取的新闻: 标题: AI在药物发现中的作用
网址: https://example.com/article1
描述: 这是一篇关于AI在药物发现中应用的文章。

标题: 人工智能如何改变制药业
网址: https://example.com/article2
描述: 探讨了AI技术在制药行业的影响。

...

最终新闻内容:
[编辑后的新闻内容]

注意:由于网络搜索的结果是实时的,实际输出可能会有所不同。


7. 扩展与优化

个性化定制

  • 增加更多的代理:可以添加更多的代理,例如主题分析助手、摘要生成助手等。
  • 自定义代理指令:根据需求修改代理的 instructions,以改变其行为。

安全与隐私考虑

  • 数据隐私:所有处理都在本地完成,确保用户数据的安全性。
  • 搜索引擎选择:可以替换为其他搜索引擎,或者使用本地数据源。

可能的改进方向

  • 增加错误处理:例如,当搜索结果为空时,提供友好的提示或采取替代措施。
  • 改进编辑助手:引入更复杂的自然语言处理技术,提升编辑质量。
  • 用户交互界面:开发图形用户界面(GUI)或命令行界面,提升用户体验。

8. 总结

本教案详细介绍了如何构建一个基于本地 AI 的新闻聚合器,利用 Ollama 的 Llama 3.2 模型、Swarm 代理编排框架和 DuckDuckGo 搜索,实现了一个功能完整、可扩展的系统。

主要收获

  • 理解了本地 AI 技术的应用:在保护隐私的同时,实现强大的数据处理能力。
  • 掌握了 Swarm 框架的基本使用:能够创建、管理和协调多个 AI 代理。
  • 学会了整合网络搜索功能:利用公开的 API,为系统提供实时的数据支持。

未来展望

随着人工智能技术的不断发展,基于本地 AI 的应用将越来越普及。通过深入理解和实践这些技术,我们可以开发出更多创新、实用的工具,满足个性化的需求。


### 关于 LangGraph 的学习资源 对于希望深入了解或开始学习 LangGraph 的开发者而言,存在多种高质量的学习材料可供选择。 #### 官方文档与教程 官方文档提供了详尽的概念介绍和技术细节解析[^1]。通过这些资料能够掌握如何创建复杂的智能体应用程序以及理解其核心组件的工作原理。此外,《LangGraph快速入门》不仅涵盖了安装配置过程中的要点还包含了实际案例研究来帮助新手更快地上手实践。 #### 实战指南 针对那些希望通过项目驱动方式深入探索该技术框架的人士,《实战LangChain(四):LangGraph入门——状态管理与基础结构》提供了一个很好的起点[^2]。这份笔记记录了一系列具体的实现方法论,并附带完整的代码样例用于演示不同功能模块之间的协作机制。 #### 基础概念详解 为了更好地理解和运用StatefulGraph这一重要特性,在参考资料中有专门章节解释了什么是状态信息及其传递规则[^3]。这部分内容强调了自定义状态类型的灵活性,即可以通过继承`TypeDict`类来自由设定所需的状态参数并控制它们在整个计算流程里的演变规律。 ```python from typing import TypedDict, Any class CustomState(TypedDict): variable_1: str variable_2: int variable_3: float variable_4: bool def update_state(current_state: CustomState, new_data:Any)->CustomState: updated = current_state.copy() # 更新逻辑... return updated ``` 上述代码片段展示了怎样基于给定模板扩展新的状态表示形式,并编写函数处理状态转换的过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值