跳到主要內容
Open In ColabOpen on GitHub

NVIDIA NIMs

langchain-nvidia-ai-endpoints 套件包含 LangChain 整合,用於建構使用 NVIDIA NIM 推論微服務上模型之應用程式。NIM 支援來自社群以及 NVIDIA 的跨領域模型,例如聊天、嵌入和重新排序模型。這些模型經過 NVIDIA 優化,可在 NVIDIA 加速基礎架構上提供最佳效能,並部署為 NIM,這是一種易於使用的預建容器,只需在 NVIDIA 加速基礎架構上使用單一命令即可在任何地方部署。

NVIDIA 託管的 NIM 部署可在 NVIDIA API 目錄上進行測試。經過測試後,可以使用 NVIDIA AI Enterprise 授權從 NVIDIA 的 API 目錄匯出 NIM,並在本地或雲端執行,讓企業擁有其 IP 和 AI 應用程式的所有權和完全控制權。

NIM 以每個模型為基礎打包為容器映像檔,並透過 NVIDIA NGC Catalog 作為 NGC 容器映像檔發布。NIM 的核心是為在 AI 模型上執行推論提供簡單、一致且熟悉的 API。

此範例說明如何使用 LangChain 透過 NVIDIAEmbeddings 類別與支援的 NVIDIA Retrieval QA Embedding Model 互動,以進行檢索增強生成

有關透過此 API 存取聊天模型的更多資訊,請查看 ChatNVIDIA 文件。

安裝

%pip install --upgrade --quiet  langchain-nvidia-ai-endpoints

設定

開始使用

  1. NVIDIA 建立一個免費帳戶,該帳戶託管 NVIDIA AI Foundation 模型。

  2. 選擇「Retrieval」選項卡,然後選擇您想要的模型。

  3. 在「Input」下,選擇「Python」選項卡,然後點擊「Get API Key」。然後點擊「Generate Key」。

  4. 複製並將產生的金鑰儲存為 NVIDIA_API_KEY。從那裡,您應該可以存取端點。

import getpass
import os

# del os.environ['NVIDIA_API_KEY'] ## delete key and reset
if os.environ.get("NVIDIA_API_KEY", "").startswith("nvapi-"):
print("Valid NVIDIA_API_KEY already in environment. Delete to reset")
else:
nvapi_key = getpass.getpass("NVAPI Key (starts with nvapi-): ")
assert nvapi_key.startswith("nvapi-"), f"{nvapi_key[:5]}... is not a valid key"
os.environ["NVIDIA_API_KEY"] = nvapi_key

我們應該能夠在列表中看到一個嵌入模型,該模型可以與 LLM 結合使用,以實現有效的 RAG 解決方案。我們可以透過 NVIDIAEmbeddings 類別與此模型以及 NIM 支援的其他嵌入模型進行互動。

在 NVIDIA API Catalog 上使用 NIM

初始化嵌入模型時,您可以透過傳遞模型來選擇模型,例如下面的 NV-Embed-QA,或者不傳遞任何引數來使用預設模型。

from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings

embedder = NVIDIAEmbeddings(model="NV-Embed-QA")
API 參考文檔:NVIDIAEmbeddings

此模型是微調的 E5-large 模型,它支援預期的 Embeddings 方法,包括

  • embed_query:為查詢範例產生查詢嵌入。

  • embed_documents:為您想要搜尋的文件列表產生段落嵌入。

  • aembed_query/aembed_documents:上述方法的非同步版本。

使用自託管 NVIDIA NIM

準備好部署時,您可以使用 NVIDIA NIM(包含在 NVIDIA AI Enterprise 軟體授權中)自託管模型,並在任何地方執行它們,讓您擁有自訂項目的所有權,並完全控制您的智慧財產權 (IP) 和 AI 應用程式。

了解更多關於 NIM 的資訊

from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings

# connect to an embedding NIM running at localhost:8080
embedder = NVIDIAEmbeddings(base_url="https://127.0.0.1:8080/v1")
API 參考文檔:NVIDIAEmbeddings

相似度

以下是針對這些資料點的相似度快速測試

查詢

  • 堪察加半島的天氣如何?

  • 義大利以哪些食物聞名?

  • 我的名字是什麼?我敢打賭你不記得了...

  • 人生的意義到底是什麼?

  • 人生的意義就是享受樂趣:D

文檔

  • 堪察加半島的天氣寒冷,冬季漫長而嚴酷。

  • 義大利以義大利麵、披薩、義式冰淇淋和濃縮咖啡聞名。

  • 我無法記住個人姓名,只能提供資訊。

  • 人生的目的各不相同,通常被視為個人成就。

  • 享受人生的時刻確實是一種美好的方法。

嵌入執行時間

print("\nSequential Embedding: ")
q_embeddings = [
embedder.embed_query("What's the weather like in Komchatka?"),
embedder.embed_query("What kinds of food is Italy known for?"),
embedder.embed_query("What's my name? I bet you don't remember..."),
embedder.embed_query("What's the point of life anyways?"),
embedder.embed_query("The point of life is to have fun :D"),
]
print("Shape:", (len(q_embeddings), len(q_embeddings[0])))

文檔嵌入

print("\nBatch Document Embedding: ")
d_embeddings = embedder.embed_documents(
[
"Komchatka's weather is cold, with long, severe winters.",
"Italy is famous for pasta, pizza, gelato, and espresso.",
"I can't recall personal names, only provide information.",
"Life's purpose varies, often seen as personal fulfillment.",
"Enjoying life's moments is indeed a wonderful approach.",
]
)
print("Shape:", (len(q_embeddings), len(q_embeddings[0])))

現在我們已經產生了嵌入,我們可以對結果進行簡單的相似度檢查,看看哪些文檔會在檢索任務中觸發為合理的答案

%pip install --upgrade --quiet  matplotlib scikit-learn
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

# Compute the similarity matrix between q_embeddings and d_embeddings
cross_similarity_matrix = cosine_similarity(
np.array(q_embeddings),
np.array(d_embeddings),
)

# Plotting the cross-similarity matrix
plt.figure(figsize=(8, 6))
plt.imshow(cross_similarity_matrix, cmap="Greens", interpolation="nearest")
plt.colorbar()
plt.title("Cross-Similarity Matrix")
plt.xlabel("Query Embeddings")
plt.ylabel("Document Embeddings")
plt.grid(True)
plt.show()

提醒一下,發送到我們系統的查詢和文檔是

查詢

  • 堪察加半島的天氣如何?

  • 義大利以哪些食物聞名?

  • 我的名字是什麼?我敢打賭你不記得了...

  • 人生的意義到底是什麼?

  • 人生的意義就是享受樂趣:D

文檔

  • 堪察加半島的天氣寒冷,冬季漫長而嚴酷。

  • 義大利以義大利麵、披薩、義式冰淇淋和濃縮咖啡聞名。

  • 我無法記住個人姓名,只能提供資訊。

  • 人生的目的各不相同,通常被視為個人成就。

  • 享受人生的時刻確實是一種美好的方法。

截斷

嵌入模型通常具有固定的上下文窗口,該窗口決定了可以嵌入的最大輸入令牌數。此限制可能是硬性限制,等於模型最大輸入令牌長度,或有效限制,超過此限制,嵌入的準確性會降低。

由於模型在令牌上運作,而應用程式通常處理文本,因此應用程式很難確保其輸入保持在模型的令牌限制內。預設情況下,如果輸入過大,則會拋出例外。

為了協助解決此問題,NVIDIA 的 NIM(API Catalog 或本地)提供了一個 truncate 參數,如果輸入過大,則會在伺服器端截斷輸入。

truncate 參數有三個選項

  • "NONE":預設選項。如果輸入過大,則會拋出例外。
  • "START":伺服器從開頭(左側)截斷輸入,並根據需要丟棄令牌。
  • "END":伺服器從結尾(右側)截斷輸入,並根據需要丟棄令牌。
long_text = "AI is amazing, amazing is " * 100
strict_embedder = NVIDIAEmbeddings()
try:
strict_embedder.embed_query(long_text)
except Exception as e:
print("Error:", e)
truncating_embedder = NVIDIAEmbeddings(truncate="END")
truncating_embedder.embed_query(long_text)[:5]

RAG 檢索:

以下是 LangChain Expression Language Retrieval Cookbook 條目的初始範例的重新調整用途,但使用 AI Foundation Models 的 Mixtral 8x7B InstructNVIDIA Retrieval QA Embedding 模型在其遊樂場環境中執行。Cookbook 中的後續範例也如預期般執行,我們鼓勵您探索這些選項。

提示:我們建議使用 Mixtral 進行內部推理(即,用於資料擷取、工具選擇等的指令遵循),並使用 Llama-Chat 進行單一最終「總結,方法是根據歷史記錄和上下文為此使用者做出簡單的回應」的回應。

%pip install --upgrade --quiet  langchain faiss-cpu tiktoken langchain_community

from operator import itemgetter

from langchain_community.vectorstores import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_nvidia_ai_endpoints import ChatNVIDIA
vectorstore = FAISS.from_texts(
["harrison worked at kensho"],
embedding=NVIDIAEmbeddings(model="NV-Embed-QA"),
)
retriever = vectorstore.as_retriever()

prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"Answer solely based on the following context:\n<Documents>\n{context}\n</Documents>",
),
("user", "{question}"),
]
)

model = ChatNVIDIA(model="ai-mixtral-8x7b-instruct")

chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| model
| StrOutputParser()
)

chain.invoke("where did harrison work?")
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"Answer using information solely based on the following context:\n<Documents>\n{context}\n</Documents>"
"\nSpeak only in the following language: {language}",
),
("user", "{question}"),
]
)

chain = (
{
"context": itemgetter("question") | retriever,
"question": itemgetter("question"),
"language": itemgetter("language"),
}
| prompt
| model
| StrOutputParser()
)

chain.invoke({"question": "where did harrison work", "language": "italian"})

此頁面是否對您有幫助?