资源

搜索引擎工具

  1. duckduckgo

    • 免费
  2. serpapi

    • 100 次/月
  3. travily

    • 1000 次/月

列表

不同 agent 用途

调用 Azure 上的 model

AzureChatModel

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import os

from langchain.chat_models import AzureChatOpenAI
from langchain.schema import HumanMessage

if __name__ == "__main__":
    os.environ["OPENAI_API_TYPE"] = "azure"
    os.environ["OPENAI_API_VERSION"] = "2023-03-15-preview"
    os.environ["OPENAI_API_BASE"] = "https://wei202305.openai.azure.com/"
    os.environ["OPENAI_API_KEY"] = "<your azure key>"

    model = AzureChatOpenAI(deployment_name="gpt-35-turbo-01")

    ret = model([HumanMessage(content="Translate this sentence from English to French. I love programming.")])
    #  AIMessage(content="J'adore programmer.", additional_kwargs={}, example=False)

必填参数

  1. deployment_name='gpt-35-turbo-01'
  2. azure_endpoint="https://wei202305.openai.azure.com/"
  3. api_version="2023-03-15-preview"
  4. api_key="…"
标准调用例子:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from langchain.schema import HumanMessage
from langchain.chat_models import AzureChatOpenAI

AzureChatOpenAI(
    azure_deployment='gpt-35-turbo-01',
    api_key='0b4dfdf1786a1f84e0f9aba1a1ce2eeadfdfd1',
    azure_endpoint='https://hello202323434.openai.azure.com',
    api_version='2023-03-15-preview').invoke([HumanMessage(content='your name?')])

Out[24]: AIMessage(content="I am an AI language model created by OpenAI called GPT-3. I don't have a personal name, but you can refer to me as ChatGPT.")

AzureChatOpenAI(
    azure_deployment='gpt-35-turbo-01',
    api_key='0b4b1786adfdfdf4e0f1ce2eea171',
    azure_endpoint='https://wedi202dfdf.openai.azure.com',
    api_version='2023-03-15-preview')([HumanMessage(content='your name?')])

Out[25]: AIMessage(content="I am an AI language model created by OpenAI and I don't have a personal name. You can call me OpenAI or ChatGPT. How can I assist you today?")
不使用 HumanMessage, 直接 invoke(str) 例子:
1
2
3
4
5
AzureChatOpenAI(
    azure_deployment='gpt-35-turbo-01',
    api_key='0b4b1786adfdfdf4e0f1ce2eea171',
    azure_endpoint='https://wedi202dfdf.openai.azure.com',
    api_version='2023-03-15-preview')('your name?')

AzureOpenAIEmbeddings

1
2
3
4
In [3]: from langchain.embeddings import AzureOpenAIEmbeddings

In [4]: AzureOpenAIEmbeddings(azure_deployment='text-embedding-ada-002', api_key='0b4b1786a1f84e0f9ab34er3dfdfce2eea171', azure_endpoint='https://hello334343.openai.azure.com/').embed_query('hell
   ...: o')

Chain 的调用

调用顺序:

  • self.__call__() –> self.invoke() –> self._call
  • self.acall() –> self.ainvoke() –> self._acall

Chain 的子类

  • AgentExecutor

基础类

Runnable

lanchain_core.runnables.base.Runnable

许多功能的基础类

invoke()
input -> output
batch()
a list of input -> a list of output, parallel 平行执行
stream()
input -> stream output
RunnableSequence
lanchain_core.runnables.base.RunnableSequence
RunnableParallel
lanchain_core.runnables.base.RunnableParallel

Agent 和 AgentExecutor

参考:

agent 的一般逻辑:

  • 负责把回答的问题通过 llm 分解成可是使用 tools 可是解决的问题
  • 调用合适的 tool, 回答问题
  • agent 本身可以利用 llm 自己的能力处理 tools 解决不了的问题

    • 判断问题是否解决
    • 一般性的问题回答,例如:问好,hello 等
    • 判断使用哪个工具
    • 判断工具回答结果
    • 判断接下来要使用哪个工具
  • agent 能够结合多个 tool 类回答问题,例如:tool_1 的回答作为 tool_2 的输入
  • 调用的工具 tools:

    • 知识库,eg: vector db
    • 搜索引擎
    • 程序,eg: python 函数等
    • 数据库
  • 功能分解:

    Observation
    观察,上一步的执行结果获取
    Thought
    思考,针对上一步的结果,分析(1)问题解决了?(2)下一步使用什么工具
    Action
    行动,运行工具
    ?
    后续步骤: Observation, Thought, Action, …, Thought –> Answer

创建的 agent:

  • 一般创建的 agent 是 AgentExecutor, 内部包含了 llm 、tools、 agent_object(Agent)
  • 通过 AgentType(string 类型) 映射到 AGENT_TYPE 具体的类 类构建 agent_object

AgentExecutor

AgentExecutor 本身是 Chain 的一个 子类

Tool

方法调用步骤

顺序:tool.run() -> tool._run() -> tool.func()

Customize Tool

参考:

自定义:

  • 可以设置的项

    name
    tool name :: 函数名,或者另设
    description
    tool 描述
    args_schema
    args 类型, arg 更多描述,通过 args_schema (一个 pydantic BaseModel) 额外设置

创建方法:

  • tool decorator
  • 继承 BaseTool 类
  • 使用 StructuredTool.from_function()

http api 接入模型

这里主要记录,如何接入通过 server 暴露的模型访问

  • ollama 接口
  • lamacpp server 接口
  • 其他 server api 接口

LLamaAPI hosted 接入

参考:

1
2
3
4
5
6
7
8
from llamaapi import LlamaAPI

# Replace 'Your_API_Token' with your actual API token
llama = LlamaAPI("Your_API_Token")

from langchain_experimental.llms import ChatLlamaAPI

model = ChatLlamaAPI(client=llama)

vllm server 接入

参考:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from langchain_openai import ChatOpenAI

inference_server_url = "http://localhost:8000/v1"

chat = ChatOpenAI(
    model="mosaicml/mpt-7b",
    openai_api_key="EMPTY",
    openai_api_base=inference_server_url,
    max_tokens=5,
    temperature=0,
)

llamacpp server 接入

参考:

1
2
3
4
5
6
7
8
9
from langchain_community.llms import VLLMOpenAI

llm = VLLMOpenAI(
    openai_api_key="EMPTY",
    openai_api_base="http://localhost:8000/v1",
    model_name="tiiuae/falcon-7b",
    model_kwargs={"stop": ["."]},
)
print(llm.invoke("Rome is"))

langgraph

参考:

概念:

  • 入口 entrypoint:

    • 指定入口 Node 是哪一个
    • MessageGraph.set_entry_point("node_name")
  • state

    • state 是 langgraph 的重要概念,node 会更新 state
    • state 的创建和传递

      • LangGraph 创建 state
      • 输入 message 会被放入到 state
      • state 被传入下一个执行的 node
      • node 执行后,output message 会放入到 state
    • state 的可能取值:

      • list
      • list[BaseMessage]

        • 消息列表,eg: [HumanMessage(), AIMessage()]
        • 使用例子:

          • 一个 langchain model 作为一个 MessageGraph 的 Node 可以正常处理传入的 state

            1
            2
            3
            4
            
            def call_oracle(messages: list):
                return model.invoke(message)
            
            graph.add_node("oracle", call_oracle)
          • 注意: langchain Chain 接受的是 dict, 不是 list, 所以 不能作为 MessageGraph 的 Node
    • state 中的 额外信息

      • 通过 BaseMessage.additional_kwargs: dict, 传递

        • 比如: openai function call 功能:

           1
           2
           3
           4
           5
           6
           7
           8
           9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          
          from langchain_openai import ChatOpenAI
          
          llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
          llm_with_tools = llm.bind_tools([Multiply])
          llm_with_tools.invoke("what's 3 * 12")
          
          AIMessage(
              content="",
              additional_kwargs={
                  "tool_calls": [
                      {
                          "id": "call_Q8ZQ97Qrj5zalugSkYMGV1Uo",
                          "function": {"arguments": '{"a":3,"b":12}', "name": "Multiply"},
                          "type": "function",
                      }
                  ]
              },
          )
          • 使用 additional_kwargs, 通过判断 tool_calls 中使用的 function -> name 来判断之前的 Node 推荐调用哪些 tool (function)
  • node

    • node 有名称和能够把 state 作为输入的 callable

      • name: 名称
      • callable(state: list[BaseMessage])

        • eg: model
  • router 和 conditional edges

    • conditional edge 包含内容:

      • router 函数: router_callable(state: list[BaseMessage]): router 判断上一步 state 应该被分发到哪个 node
      • 返回值和 Node 映射关系: return_value_2_node_name: dict: router 函数的返回值 和 MessageGraph 中的 Node 的名称映射
    • 使用逻辑: conditional edge 在执行完上一个 Node 后,调用 router

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      
      def router(state: List[BaseMessage]):
          tool_calls = state[-1].additional_kwargs.get("tool_calls", [])
          if len(tool_calls):
              return "multiply"
          else:
              return "end"
      
      graph.add_conditional_edges("oracle", router, {
          "multiply": "multiply",
          "end": END,
      })
      • 解释:

        • 这里的 router 判断 state 中最后一个 message 的信息,决定是调用 multply Node, 还是走到 END edge

MessageGraph

MessageGraph 中的 state 是一个 list[BaseMessage]

StateGraph

StateGraph 中的 state 是一个 dict->messages: list[BaseMesssage]

state 数据结构:

1
2
class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add]

格式化输出

参考:

使用 json, pydantic, yaml, … 格式化模型的输出结果,直接获得格式化对象。