开源 AI 食谱文档

从任何 LLM 推理提供程序创建 Transformers Agent

Hugging Face's logo
加入 Hugging Face 社区

并获取增强的文档体验

开始使用

Open In Colab

从任何 LLM 推理提供程序创建 Transformers Agent

作者:Aymeric Roucher

本教程建立在 Agent 知识的基础上:要了解更多关于 Agent 的信息,您可以从 此入门笔记本 开始

Transformers Agents 是一个用于构建 Agent 的库,使用 LLM 在 llm_engine 参数中为其提供动力。此参数旨在让用户最大限度地自由选择任何 LLM。

让我们看看如何从一些领先提供商的 API 构建此 llm_engine

HuggingFace 无服务器 API 和专用端点

Transformers Agents 提供了一个内置的 HfEngine 类,允许您通过无服务器 API 或您自己的专用端点使用 Hub 上的任何模型。这是使用 HF Agents 的首选方法。

!pip install openai anthropic "transformers[agents]" --upgrade -q
from huggingface_hub import notebook_login

notebook_login()
>>> from transformers.agents import HfApiEngine, ReactCodeAgent

>>> repo_id = "meta-llama/Meta-Llama-3.1-8B-Instruct"
>>> endpoint_url = "your_endpoint_url"

>>> llm_engine = HfApiEngine(model=repo_id)  # you could use model=endpoint_url here

>>> agent = ReactCodeAgent(tools=[], llm_engine=llm_engine)

>>> agent.run("What's the 10th Fibonacci number?")
['unicodedata', 're', 'math', 'collections', 'queue', 'itertools', 'random', 'time', 'stat', 'statistics']

Agent 的 llm_engine 初始化参数可以是一个简单的可调用对象,例如

def llm_engine(messages, stop_sequences=[]) -> str:
    return response(messages)

此可调用对象是 llm 引擎的核心。它应满足以下要求

  • 聊天模板 格式的消息列表作为输入,并输出一个 str
  • 接受一个 stop_sequences 参数,其中 Agent 系统将传递它应该停止生成的序列。

让我们仔细看看我们使用的 HfEngine 代码

from typing import List, Dict
from transformers.agents.llm_engine import MessageRole, get_clean_message_list
from huggingface_hub import InferenceClient

llama_role_conversions = {
    MessageRole.TOOL_RESPONSE: MessageRole.USER,
}


class HfApiEngine:
    def __init__(self, model: str = "meta-llama/Meta-Llama-3.1-8B-Instruct"):
        self.model = model
        self.client = InferenceClient(model=self.model, timeout=120)

    def __call__(self, messages: List[Dict[str, str]], stop_sequences=[]) -> str:
        # Get clean message list
        messages = get_clean_message_list(messages, role_conversions=llama_role_conversions)

        # Get LLM output
        response = self.client.chat_completion(messages, stop=stop_sequences, max_tokens=1500)
        response = response.choices[0].message.content

        # Remove stop sequences from LLM output
        for stop_seq in stop_sequences:
            if response[-len(stop_seq) :] == stop_seq:
                response = response[: -len(stop_seq)]
        return response

这里引擎不是函数,而是一个带有 __call__ 方法的类,它增加了存储属性(例如客户端)的可能性。

我们还使用 get_clean_message_list() 实用程序将连续消息连接到同一角色。此方法采用 role_conversions 参数将 Transformers Agents 中支持的角色范围转换为您的 LLM 接受的角色。

此食谱可以适用于任何 LLM!让我们看看其他示例。

使食谱适用于任何 LLM

使用上述食谱,您可以使用任何 LLM 推理源作为您的 llm_engine。请记住两个主要约束条件

  • llm_engine 是一个可调用对象,它以 聊天模板 格式的消息列表作为输入,并输出一个 str
  • 它接受一个 stop_sequences 参数。

OpenAI

import os
from openai import OpenAI

openai_role_conversions = {
    MessageRole.TOOL_RESPONSE: MessageRole.USER,
}


class OpenAIEngine:
    def __init__(self, model_name="gpt-4o"):
        self.model_name = model_name
        self.client = OpenAI(
            api_key=os.getenv("OPENAI_API_KEY"),
        )

    def __call__(self, messages, stop_sequences=[]):
        messages = get_clean_message_list(messages, role_conversions=openai_role_conversions)

        response = self.client.chat.completions.create(
            model=self.model_name,
            messages=messages,
            stop=stop_sequences,
            temperature=0.5,
        )
        return response.choices[0].message.content

Anthropic

from anthropic import Anthropic, AnthropicBedrock


# Cf this page for using Anthropic from Bedrock: https://docs.anthropic.com/en/api/claude-on-amazon-bedrock
class AnthropicEngine:
    def __init__(self, model_name="claude-3-5-sonnet-20240620", use_bedrock=False):
        self.model_name = model_name
        if use_bedrock:
            self.model_name = "anthropic.claude-3-5-sonnet-20240620-v1:0"
            self.client = AnthropicBedrock(
                aws_access_key=os.getenv("AWS_BEDROCK_ID"),
                aws_secret_key=os.getenv("AWS_BEDROCK_KEY"),
                aws_region="us-east-1",
            )
        else:
            self.client = Anthropic(
                api_key=os.getenv("ANTHROPIC_API_KEY"),
            )

    def __call__(self, messages, stop_sequences=[]):
        messages = get_clean_message_list(messages, role_conversions=openai_role_conversions)
        index_system_message, system_prompt = None, None
        for index, message in enumerate(messages):
            if message["role"] == MessageRole.SYSTEM:
                index_system_message = index
                system_prompt = message["content"]
        if system_prompt is None:
            raise Exception("No system prompt found!")

        filtered_messages = [message for i, message in enumerate(messages) if i != index_system_message]
        if len(filtered_messages) == 0:
            print("Error, no user message:", messages)
            assert False

        response = self.client.messages.create(
            model=self.model_name,
            system=system_prompt,
            messages=filtered_messages,
            stop_sequences=stop_sequences,
            temperature=0.5,
            max_tokens=2000,
        )
        full_response_text = ""
        for content_block in response.content:
            if content_block.type == "text":
                full_response_text += content_block.text
        return full_response_text

后续步骤

继续使用您自己的 LLM 推理提供程序为 transformers.agents 实现您的 llm_engine

然后要使用这个闪亮的新 llm_engine,请查看以下用例

< > 在 GitHub 上更新