以编程方式使用文档

langchain-nvidia-ai-endpoints 软件包包含由 NVIDIA AI 基础模型驱动的 LangChain 聊天模型和嵌入集成,并托管在 NVIDIA API 目录.

NVIDIA AI 基础模型是由社区和 NVIDIA 构建的模型,经过优化可在 NVIDIA 加速基础设施上提供最佳性能。您可以使用 API 查询 NVIDIA API 目录上可用的实时端点,从 DGX 托管的云计算环境快速获取结果,或者可以使用 NVIDIA AI Enterprise 许可证附带的 NVIDIA NIM 从 NVIDIA 的 API 目录下载模型。在本地运行模型的能力使您的企业拥有自定义的所有权,并完全控制您的 IP 和 AI 应用程序。

NIM microservices are packaged as container images on a per model/model family basis and are distributed as NGC container images through the NVIDIA NGC 目录。从根本上讲,NIM 微服务是提供交互式 API 的容器,用于在 AI 模型上运行推理。

本示例介绍如何使用 LangChain 与支持的 NVIDIA 检索问答嵌入模型 配合使用 检索增强生成 ,通过 NVIDIAEmbeddings class.

有关通过此 API 访问聊天模型的更多信息,请参阅 ChatNVIDIA documentation.

安装软件包

pip install -qU langchain-nvidia-ai-endpoints

访问 NVIDIA API 目录

要获取 NVIDIA API 目录的访问权限,请执行以下操作:

  1. NVIDIA API 目录 上创建一个免费账户并登录。
  2. 点击您的个人资料图标,然后点击 **API 密钥**。 **API 密钥** 页面出现。
  3. 点击 **生成 API 密钥**。 **生成 API 密钥** 窗口出现。
  4. 点击 **生成密钥**。 **API 密钥已授予**,您的密钥出现。
  5. 复制并保存密钥为 NVIDIA_API_KEY.
  6. 要验证您的密钥,请使用以下代码。
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

现在您可以使用密钥访问 NVIDIA API 目录上的端点。

使用 API 目录

初始化嵌入模型时,您可以通过传递来选择模型,例如 NV-Embed-QA ,或者通过不传递任何参数来使用默认值。

from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings

embedder = NVIDIAEmbeddings(model="NV-Embed-QA")

该模型是一个微调的 E5-large 模型,支持预期的 Embeddings 方法,包括:

  • - embed_query:为查询样本生成查询嵌入。
  • - embed_documents:为要搜索的文档列表生成段落嵌入。
  • - aembed_query/aembed_documents:上述内容的异步版本。

使用 NVIDIA NIM 微服务进行自托管

当您准备好部署 AI 应用程序时,可以使用 NVIDIA NIM 自托管模型。更多信息,请参阅 NVIDIA NIM 微服务.

以下代码连接到本地托管的 NIM 微服务。

from langchain_nvidia_ai_endpoints import ChatNVIDIA, NVIDIAEmbeddings, NVIDIARerank

# connect to a chat NIM running at localhost:8000, specifying a model
llm = ChatNVIDIA(base_url="http://localhost:8000/v1", model="meta/llama3-8b-instruct")

# connect to an embedding NIM running at localhost:8080
embedder = NVIDIAEmbeddings(base_url="http://localhost:8080/v1")

# connect to a reranking NIM running at localhost:2016
ranker = NVIDIARerank(base_url="http://localhost:2016/v1")

**相似度**

以下是这些数据点的相似度快速测试:

Queries:

  • - 堪察加的天气怎么样?
  • - 意大利以什么食物闻名?
  • - 我叫什么名字?我打赌你不记得了……
  • - 人生的意义到底是什么?
  • - 人生的意义就是玩得开心 :D

Documents:

  • - 堪察加的天气寒冷,冬季漫长而严酷。
  • - 意大利以意大利面、披萨、冰激凌和浓缩咖啡闻名。
  • - 我无法回忆个人姓名,只能提供信息。
  • - 人生的目的各不相同,通常被视为个人成就感。
  • - 享受人生的每一刻确实是一种美好的方式。

嵌入运行时

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(d_embeddings), len(d_embeddings[0])))

现在我们已经生成了嵌入,可以对结果进行简单的相似度检查,以查看哪些文档会在检索任务中被触发为合理的答案:

pip install -qU  matplotlib scikit-learn
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()

提醒一下,发送到我们系统的查询和文档是:

Queries:

  • - 堪察加的天气怎么样?
  • - 意大利以什么食物闻名?
  • - 我叫什么名字?我打赌你不记得了……
  • - 人生的意义到底是什么?
  • - 人生的意义就是玩得开心 :D

Documents:

  • - 堪察加的天气寒冷,冬季漫长而严酷。
  • - 意大利以意大利面、披萨、冰激凌和浓缩咖啡闻名。
  • - 我无法回忆个人姓名,只能提供信息。
  • - 人生的目的各不相同,通常被视为个人成就感。
  • - 享受人生的每一刻确实是一种美好的方式。

截断

嵌入模型通常有一个固定上下文窗口,决定可以嵌入的最大输入令牌数。这个限制可以是硬限制,等于模型的最大输入令牌长度,或者是有效限制,超过这个限制后嵌入的准确性会下降。

由于模型在令牌上运行,而应用程序通常处理文本,应用程序可能难以确保其输入保持在模型的令牌限制范围内。默认情况下,如果输入太大,则会抛出异常。

为帮助解决此问题,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 表达式语言检索 Cookbook 入门示例的重新改编 https://python.langchain.com/docs/expression_language/cookbook/retrieval), but executed with the AI Foundation Models' Mixtral 8x7B InstructNVIDIA Retrieval QA Embedding 模型在其 Playground 环境中可用。Cookbook 中的后续示例也能按预期运行,我们鼓励您探索这些选项。

TIP: 我们建议使用 Mixtral 进行内部推理(即数据提取、工具选择等的指令遵循),使用 Llama-Chat 进行单一的最终"总结回复——根据历史和上下文为用户生成一个简单的回复"。

pip install -qU  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\n{context}\n",
        ),
        ("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\n{context}\n"
            "\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"})

相关主题