從 OpenAI 到 Hugging Face 上的開放 LLM (整合 Messages API)

釋出於 2024 年 2 月 8 日
在 GitHub 上更新

我們很高興地宣佈,為了提供與文字生成推理 (TGI) 和推理端點 (Inference Endpoints) 的 OpenAI 相容性,我們正式引入了 Messages API。

從 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 CrupiRyght 首席技術官

新的 Messages API 現在也已在推理端點中可用,支援專用和無伺服器兩種模式。為了讓您快速上手,我們提供了詳細的示例,教您如何

限制: Messages API 目前不支援函式呼叫 (function calling),並且僅適用於在其分詞器配置 (tokenizer configuration) 中定義了 `chat_template` 的大語言模型,例如 Mixtral 8x7B Instruct

建立推理端點

推理端點 (Inference Endpoints) 提供了一個安全、生產級的解決方案,可輕鬆地在由 Hugging Face 管理的專用基礎設施上部署 Hub 上的任何機器學習模型。

在本例中,我們將使用文字生成推理 (Text Generation Inference) 將一個經過微調的 Mixtral 模型 Nous-Hermes-2-Mixtral-8x7B-DPO 部署到推理端點。

我們只需在UI 介面上點選幾下即可部署模型,或者利用 `huggingface_hub` Python 庫以程式設計方式建立和管理推理端點。這裡我們演示如何使用 Hub 庫。

在下面的 API 呼叫中,我們需要指定端點名稱和模型倉庫,以及任務型別為 `text-generation`。本例中,我們使用 `protected` 型別,這樣訪問已部署的端點就需要一個有效的 Hugging Face 令牌。我們還需要配置硬體要求,如供應商、區域、加速器、例項型別和大小。您可以透過此 API 呼叫檢視可用的資源選項,並在我們的目錄這裡檢視部分模型的推薦配置。

注意:您可能需要傳送郵件至 api-enterprise@huggingface.co 申請配額升級。

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 的支援使得推理端點直接與 OpenAI Chat Completion API 相容。這意味著任何現有透過 OpenAI 客戶端庫使用 OpenAI 模型的指令碼都可以直接替換為使用任何在 TGI 端點上執行的開放大語言模型!

透過這種無縫過渡,您可以立即利用開放模型帶來的眾多優勢:

  • 完全控制和透明的模型與資料
  • 不再擔心速率限制
  • 能夠根據您的特定需求完全自定義系統

讓我們看看如何實現。

使用 Python 客戶端

下面的例子展示瞭如何使用 OpenAI Python 庫 進行這種轉換。只需將 `` 替換為您的端點 URL (確保包含 `v1/` 字尾),並將 `` 欄位填充為有效的 Hugging Face 使用者令牌。`` 可以從推理端點 UI 中獲取,也可以從我們上面建立的端點物件 `endpoint.url` 中獲取。

然後,我們可以像平常一樣使用客戶端,向推理端點傳遞一個訊息列表以流式獲取響應。

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` 例項,並按如下方式傳入您的 `` 和 ``:

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` 類。這使得所有以前的程式碼只需更改一行程式碼即可與我們的端點配合使用。現在讓我們在一個簡單的 RAG 管道中使用這樣宣告的 LLM,來回答一個關於 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://huggingface.co/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 管道中使用它。請記住,您在推理端點中先前選擇的 `MAX_INPUT_LENGTH` 將直接影響模型可以處理的檢索到的塊 (chunk) 的數量 (`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://huggingface.co/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()

總結

文字生成推理 (TGI) 中的新 Messages API 為從 OpenAI 模型到開放大語言模型的平滑過渡提供了一條路徑。我們迫不及待地想看到您將利用在 TGI 上執行的開放大語言模型來驅動哪些用例!

請參閱此 notebook,獲取本文中程式碼的可執行版本。

社群

註冊登入 發表評論

© . This site is unofficial and not affiliated with Hugging Face, Inc.