跳到正文
原文
Hugging Face Blog·· 2024-02-08精选AI 评分60

HF Mirror 为 TGI 与 Inference Endpoints 推出 Messages API,兼容 OpenAI Chat Completion

From OpenAI to Open LLMs with Messages API on HF Mirror

AI 导读

Hugging Face 为 Text Generation Inference(TGI)和 Inference Endpoints 推出 Messages API。

推荐理由

TGI 1.4.0 起提供 OpenAI 兼容的 Messages API,读者可据此评估把现有 OpenAI 代码迁移到开源模型的成本。

正文 · AI 翻译

我们很高兴推出 Messages API,为文本生成推理(TGI)和推理端点提供 OpenAI 兼容性。

从 1.4.0 版本开始,TGI 提供了一个与 OpenAI Chat Completion API 兼容的 API。新的 Messages API 让客户和用户能够无缝地从 OpenAI 模型过渡到开放 LLM。该 API 可直接与 OpenAI 的客户端库或第三方工具(如 LangChain 或 LlamaIndex)配合使用。

“新的具有 OpenAI 兼容性的 Messages API 使 Ryght 的实时 GenAI 编排平台可以轻松地将 LLM 用例从 OpenAI 切换到开放模型。我们在推理端点上从 GPT4 迁移到 Mixtral/Llama2 毫不费力,现在我们拥有了简化的工作流程,可以更好地控制我们的 AI 解决方案。” - Johnny Crupi,首席技术官,就职于 Ryght

新的 Messages API 现已在推理端点中提供,涵盖专用和无服务器两种类型。为了帮助您快速上手,我们提供了详细示例,说明如何:

限制: Messages API 目前不支持函数调用,并且仅适用于在其 tokenizer 配置中定义了 chat_template 的 LLM,例如 Mixtral 8x7B Instruct。

创建推理端点

推理端点提供了一种安全的生产级解决方案,可轻松地将 Hub 中的任何机器学习模型部署到由 HF Mirror 管理的专用基础设施上。

在此示例中,我们将使用 文本生成推理 将一个微调过的 Mixtral 模型 Nous-Hermes-2-Mixtral-8x7B-DPO 部署到推理端点。

我们可以在 UI 中点击几下 就部署模型,或者利用 huggingface_hub Python 库以编程方式创建和管理推理端点。这里我们演示使用 Hub 库。

在下面展示的 API 调用中,我们需要指定端点名称和模型仓库,以及 text-generation 的任务。在此示例中,我们使用 protected 类型,因此访问已部署的端点需要有效的 HF Mirror token。我们还需要配置硬件要求,如供应商、区域、加速器、实例类型和大小。您可以 使用此 API 调用 查看可用资源选项列表,并在我们的目录中 此处 查看精选模型的推荐配置。

注意:您可能需要通过发送电子邮件至 [email protected] 来请求配额升级

from huggingface_hub import create_inference_endpoint

endpoint = create_inference_endpoint(
    "nous-hermes-2-mixtral-8x7b-demo",
    repository="NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO",
    framework="pytorch",
    task="text-generation",
    accelerator="gpu",
    vendor="aws",
    region="us-east-1",
    type="protected",
    instance_type="nvidia-a100",
    instance_size="x2",
    custom_image={
        "health_route": "/health",
        "env": {
            "MAX_INPUT_LENGTH": "4096",
            "MAX_BATCH_PREFILL_TOKENS": "4096",
            "MAX_TOTAL_TOKENS": "32000",
            "MAX_BATCH_TOTAL_TOKENS": "1024000",
            "MODEL_ID": "/repository",
        },
        "url": "ghcr.io/huggingface/text-generation-inference:sha-1734540", # use this build or newer
    },
)

endpoint.wait()
print(endpoint.status)

我们的部署需要几分钟才能启动。我们可以使用 .wait() 实用程序阻塞正在运行的线程,直到端点达到最终的“running”状态。一旦运行,我们可以确认其状态并通过 UI Playground 试用一下:

IE UI Overview

很好,我们现在有了一个可以正常工作的端点!

💡 使用 huggingface_hub 部署时,您的端点默认会在空闲 15 分钟后缩容至零,以在非活动期间优化成本。请查看 Hub Python 库文档 以了解可用于管理端点生命周期的所有功能。

将推理端点与 OpenAI 客户端库一起使用

TGI 对 Messages 的支持使 Inference Endpoints 直接兼容 OpenAI Chat Completion API。这意味着任何通过 OpenAI 客户端库使用 OpenAI 模型的现有脚本,都可以直接替换为使用任何运行在 TGI 端点上的开源 LLM!

借助这种无缝切换,您可以立即享受开源模型带来的诸多好处:

  • 对模型和数据的完全控制与透明度
  • 不再需要担心速率限制
  • 能够根据您的具体需求完全自定义系统

让我们看看如何操作。

使用 Python 客户端

下面的示例展示了如何使用 OpenAI Python 库 完成这一过渡。只需将 <ENDPOINT_URL> 替换为您的端点 URL(请确保包含 v1/ 后缀),并将 <HF_API_TOKEN> 字段填入有效的 HF Mirror 用户令牌。<ENDPOINT_URL> 可以从 Inference Endpoints UI 中获取,也可以从我们上面通过 endpoint.url 创建的端点对象中获取。

然后,我们可以像往常一样使用客户端,传入一个消息列表,从我们的 Inference Endpoint 流式获取响应。

from openai import OpenAI

# initialize the client but point it to TGI
client = OpenAI(
    base_url="<ENDPOINT_URL>" + "/v1/",  # replace with your endpoint url
    api_key="<HF_API_TOKEN>",  # replace with your token
)
chat_completion = client.chat.completions.create(
    model="tgi",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Why is open-source software important?"},
    ],
    stream=True,
    max_tokens=500
)

# iterate and print stream
for message in chat_completion:
    print(message.choices[0].delta.content, end="")

在幕后,TGI 的 Messages API 会自动使用其 聊天模板,将消息列表转换为模型所需的指令格式。

💡 某些 OpenAI 功能(如函数调用)与 TGI 不兼容。目前,Messages API 支持以下聊天补全参数:stream、max_tokens、frequency_penalty、logprobs、seed、temperature 和 top_p。

使用 JavaScript 客户端

下面是上面相同的流式示例,但使用的是 OpenAI JavaScript/TypeScript 库。

import OpenAI from "openai";

const openai = new OpenAI({
  baseURL: "<ENDPOINT_URL>" + "/v1/", // replace with your endpoint url
  apiKey: "<HF_API_TOKEN>", // replace with your token
});

async function main() {
  const stream = await openai.chat.completions.create({
    model: "tgi",
    messages: [
      { role: "system", content: "You are a helpful assistant." },
      { role: "user", content: "Why is open-source software important?" },
    ],
    stream: true,
    max_tokens: 500,
  });
  for await (const chunk of stream) {
    process.stdout.write(chunk.choices[0]?.delta?.content || "");
  }
}

main();

与 LangChain 和 LlamaIndex 集成

现在,让我们看看如何在您首选的 RAG 框架中使用这个新创建的端点。

如何在 LangChain 中使用

要在 LangChain 中使用它,只需创建一个 ChatOpenAI 的实例,并传入您的 <ENDPOINT_URL> 和 <HF_API_TOKEN>,如下所示:

from langchain_community.chat_models.openai import ChatOpenAI

llm = ChatOpenAI(
    model_name="tgi",
    openai_api_key="<HF_API_TOKEN>",
    openai_api_base="<ENDPOINT_URL>" + "/v1/",
)
llm.invoke("Why is open-source software important?")

我们可以直接使用原本用于 OpenAI 模型的同一个 ChatOpenAI 类。这使得所有之前的代码只需更改一行代码即可与我们的端点配合使用。 现在,让我们以这种方式声明的 LLM 用于一个简单的 RAG 管道,以回答有关一篇 HF 博客文章内容的问题。

from langchain_core.runnables import RunnableParallel
from langchain_community.embeddings import HuggingFaceEmbeddings

# Load, chunk and index the contents of the blog
loader = WebBaseLoader(
    web_paths=("https://hf-mirror.com/blog/open-source-llms-as-agents",),
)
docs = loader.load()

# Declare an HF embedding model and vector store
hf_embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-large-en-v1.5")

text_splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(documents=splits, embedding=hf_embeddings)

# Retrieve and generate using the relevant pieces of context
retriever = vectorstore.as_retriever()
prompt = hub.pull("rlm/rag-prompt")

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

rag_chain_from_docs = (
    RunnablePassthrough.assign(context=(lambda x: format_docs(x["context"])))
    | prompt
    | llm
    | StrOutputParser()
)

rag_chain_with_source = RunnableParallel(
    {"context": retriever, "question": RunnablePassthrough()}
).assign(answer=rag_chain_from_docs)

rag_chain_with_source.invoke("According to this article which open-source model is the best for an agent behaviour?")
{
    "context": [...],
    "question": "According to this article which open-source model is the best for an agent behaviour?",
    "answer": " According to the article, Mixtral-8x7B is the best open-source model for agent behavior, as it performs well and even beats GPT-3.5. The authors recommend fine-tuning Mixtral for agents to potentially surpass the next challenger, GPT-4.",
}

如何在 LlamaIndex 中使用

类似地,您也可以在 LlamaIndex 中使用 TGI 端点。我们将使用 OpenAILike 类,并通过配置一些附加参数(即 is_local、is_function_calling_model、is_chat_model、context_window)来实例化它。请注意,上下文窗口参数应与您端点之前设置的 MAX_TOTAL_TOKENS 值相匹配。

from llama_index.llms import OpenAILike

# Instantiate an OpenAILike model
llm = OpenAILike(
    model="tgi",
    api_key="<HF_API_TOKEN>",
    api_base="<ENDPOINT_URL>" + "/v1/",
    is_chat_model=True,
    is_local=False,
    is_function_calling_model=False,
    context_window=32000,
)

# Then call it
llm.complete("Why is open-source software important?")

现在我们可以在类似的 RAG 管道中使用它。请记住,之前在 Inference Endpoint 中选择的 MAX_INPUT_LENGTH 将直接影响模型能够处理的检索块数量(similarity_top_k)。

from llama_index import (
    ServiceContext,
    VectorStoreIndex,
)
from llama_index import download_loader
from llama_index.embeddings import HuggingFaceEmbedding
from llama_index.query_engine import CitationQueryEngine

SimpleWebPageReader = download_loader("SimpleWebPageReader")

documents = SimpleWebPageReader(html_to_text=True).load_data(
    ["https://hf-mirror.com/blog/open-source-llms-as-agents"]
)

# Load embedding model
embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-large-en-v1.5")

# Pass LLM to pipeline
service_context = ServiceContext.from_defaults(embed_model=embed_model, llm=llm)
index = VectorStoreIndex.from_documents(
    documents, service_context=service_context, show_progress=True
)

# Query the index
query_engine = CitationQueryEngine.from_args(
    index,
    similarity_top_k=2,
)
response = query_engine.query(
    "According to this article which open-source model is the best for an agent behaviour?"
)
According to the article, Mixtral-8x7B is the best performing open-source model for an agent behavior [5]. It even beats GPT-3.5 in this task. However, it's worth noting that Mixtral's performance could be further improved with proper fine-tuning for function calling and task planning skills [5].

清理

使用完端点后,您可以将其暂停或删除。此步骤可以通过 UI 完成,也可以像下面这样以编程方式完成。

# pause our running endpoint
endpoint.pause()

# optionally delete
endpoint.delete()

结论

Text Generation Inference 中新的 Messages API 为从 OpenAI 模型到开源 LLM 提供了平滑的过渡路径。我们迫不及待地想看到您使用运行在 TGI 上的开源 LLM 实现的各种用例!

有关文章中概述的代码的可运行版本,请参阅 此 notebook。

来源:Hugging Face Blog · hf-mirror.com