开源 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

后续步骤

继续为transformers.agents实现您自己的llm_engine,并使用您自己的LLM推理提供商!

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

< > 在 GitHub 上更新