AutoChain—轻量级且可测试的 LangChain 替代品

1,817 阅读4分钟

查看 原文 更多详细内容

介绍

AutoCHain 是 Forethought AI 公司(成立于 2017,AI 智能客服领域)开源的,先看看它对自己的介绍:AutoChain 从 LangChain 和 AutoGPT 中汲取灵感,旨在通过提供一个轻量级、可扩展的框架来解决这两个问题,开发人员可以使用 LLMs 和自定义工具构建自己的代理,并通过模拟对话自动评估不同的用户场景。有经验的 LangChain 用户会发现 AutoChain 很容易上手,因为它们共享相似但更简单的概念。我们的目标是通过简化代理定制和评估,实现生成式代理的快速迭代。

特性

  • 🚀 轻量级、可扩展的生成式代理 pipeline

  • 🔗 可使用不同自定义工具并支持 OpenAI 函数调用的代理

  • 💾 对对话历史和工具输出进行简单的内存跟踪

  • 🤖 通过模拟对话自动进行代理多轮对话评估

代码实践

下面以 OpenAI Functions Calling 和天气查询 API 结合实现查天气功能的 Agent 为例,比对下 AutoChain 和 LangChain 区别。

AutoChain

import json
from autochain.agent.openai_functions_agent.openai_functions_agent import (
    OpenAIFunctionsAgent,
)
from autochain.chain.chain import Chain
from autochain.memory.buffer_memory import BufferMemory
from autochain.models.chat_openai import ChatOpenAI
from autochain.tools.base import Tool


def get_current_weather(location: str, unit: str = "celsius"):
    """根据输入地点获取天气情况"""
    weather_info = {
        "location": location,
        "temperature": "28",
        "unit": unit,
        "forecast": ["温暖", "晴朗"],
    }
    return json.dumps(weather_info)


tools = [
    Tool(
        name="get_current_weather",
        func=get_current_weather,
        description="""根据输入地点获取天气情况""",
    )
]

if __name__ == "__main__":
    memory = BufferMemory()
    llm = ChatOpenAI(temperature=0)
    agent = OpenAIFunctionsAgent.from_llm_and_tools(llm=llm, tools=tools)
    chain = Chain(agent=agent, memory=memory)
    user_query = "今天北京天气怎么样?"
    print(f">> User: {user_query}")
    print(f">> Assistant: {chain.run(user_query)['message']}")

执行结果跟踪

>> User: 今天北京天气怎么样?
Planning

Planning output:
message content: 'hum..'; function_call: {'name': 'get_current_weather', 'arguments': '{\n  "location": "Beijing"\n}'}
Plan to take action 'get_current_weather'

Took action 'get_current_weather' with inputs '{'location': 'Beijing'}', and the tool_output is {"location": "Beijing", "temperature": "28", "unit": "celsius", "forecast": ["\u6e29\u6696", "\u6674\u6717"]}
Planning

Planning output:
message content: '今天北京的天气很好,温度为28摄氏度,天气晴朗。'; function_call: {}
>> Assistant: 今天北京的天气很好,温度为28摄氏度,天气晴朗。

LangChain

from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.chat_models import ChatOpenAI
from langchain.tools import  Tool
import json

def get_current_weather(location: str, unit: str = "celsius"):
    """根据输入地点获取天气情况"""
    weather_info = {
        "location": location,
        "temperature": "28",
        "unit": unit,
        "forecast": ["温暖", "晴朗"],
    }
    return json.dumps(weather_info)

tools = [
    Tool.from_function(
        name="get_current_weather",
        func=get_current_weather,
        description="""根据输入地点获取天气情况""",
    ),
]

if __name__ == "__main__":
    llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613")
    mrkl = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=True)
    mrkl.run("今天北京天气怎么样?")

执行结果跟踪

> Entering new AgentExecutor chain...

Invoking: `get_current_weather` with `{'location': '北京'}`


{"location": "\u5317\u4eac", "temperature": "28", "unit": "celsius", "forecast": ["\u6e29\u6696", "\u6674\u6717"]}今天北京的天气情况是温暖的,气温为28摄氏度,天气晴朗。

> Finished chain.

对比探讨

AutoChain 明显嵌套更浅一点,而且对开发人员来说直觉上更容易理解,一个特定功能的 Agent 就是一个特定工具与 LLM 的结合,实际开发过程中会面临大量 Agent 的管理和复用。这种方式也更容易对 Agent 进行嵌套,而且直接用类似 OpenAIFunctionsAgent 的声明极大的提高了代码可读性。 同时日志的输出也更加友好易懂,按照用户意图转换为执行计划,动作规划,执行计划结果返回展示

agent = OpenAIFunctionsAgent.from_llm_and_tools(llm=llm, tools=tools)
chain = Chain(agent=agent, memory=memory)

LangChain 则让写代码的人非常疑惑,这里的 Agent 初始化,直接将特定工具,LLM 和 Agent 类型整合在一起,但是实际开发过程中工具来源多样性,LLM 也是多样的,再加后面的 Agent 类型,管理起来会非常混乱。开发人员需要的是灵活组合且可管理的 Agent,统一用 initialize_agent 一次性声明固然方便,但代码维护者负担很大。

日志也是很不友好,因为你直接去读,无法感知到 Agent 的运行逻辑,除非打开全局日志(虽然详细,但是会输出一大段未处理的原始调用信息 😅)

mrkl = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=True)

结论

AutoChain 值得关注,使用体感上确实强于 LangChain,笔者本人已经准备积极拥抱 AutoChain 了,推荐大家去阅读源码,并尝试更多的案例,毕竟优雅的开发框架可以帮助自己提高效率,拥有更多 Coffee Time ☕️

参考链接