Open-Source AI Cookbook documentation

从任意的 LLM 推理提供商中创建一个 Transformers 智能体

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Open In Colab

从任意的 LLM 推理提供商中创建一个 Transformers 智能体

作者: Aymeric Roucher

本教程建立在智能体知识的基础上:要了解更多关于智能体的信息,你可以从这里介绍开始。

Transformers Agents 是一个用于构建智能体的库,它使用 LLM 在 llm_engine 参数中提供动力。这个参数的设计是为了给用户最大的自由度去选择任意 LLM。

让我们看看如何从一些主要提供商的 API 中构建这个 llm_engine

HuggingFace 无服务器 API 和专用端点

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

>>> from transformers.agents import HfEngine, ReactCodeAgent

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

>>> llm_engine = HfEngine(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']

智能体的 llm_engine 初始化参数可以是一个简单的可调用对象,如下所示:

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

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

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

让我们更仔细地看看我们使用的 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 HfEngine:
    def __init__(self, model: str = "meta-llama/Meta-Llama-3-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 智能体支持的角色的范围转换为你的 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_engine 来玩玩这些应用场景:

< > Update on GitHub