Skip to main content
Open In ColabOpen on GitHub

ChatPremAI

PremAI 是一个一站式平台,可简化生成式 AI 驱动的、稳健的、生产就绪型应用的创建过程。通过优化开发流程,PremAI 使您能够专注于提升用户体验和推动应用的整体增长。您可以通过 此处 快速开始使用我们的平台。

本示例将介绍如何使用 LangChain 通过 ChatPremAI 与不同的聊天模型进行交互。

安装和设置

我们首先安装 langchainpremai-sdk。您可以通过键入以下命令进行安装:

pip install premai langchain

在继续操作之前,请确保您已在 PremAI 上创建账户并已创建项目。如果尚未完成,请参阅快速入门指南以开始使用 PremAI 平台。创建您的第一个项目并获取 API 密钥。

from langchain_community.chat_models import ChatPremAI
from langchain_core.messages import HumanMessage, SystemMessage

在 LangChain 中设置 PremAI 客户端

导入所需模块后,我们来设置客户端。目前我们假设 project_id8。但请确保使用您自己的 project-id,否则会报错。

要将 langchain 与 prem 结合使用,您无需传递任何模型名称或使用我们的 chat-client 设置任何参数。默认情况下,它将使用 LaunchPad 中使用的模型名称和参数。

注意:如果您在设置客户端时更改了 modeltemperaturemax_tokens 等其他参数,它将覆盖 LaunchPad 中使用的现有默认配置。

import getpass
import os

# First step is to set up the env variable.
# you can also pass the API key while instantiating the model but this
# comes under a best practices to set it as env variable.

if os.environ.get("PREMAI_API_KEY") is None:
os.environ["PREMAI_API_KEY"] = getpass.getpass("PremAI API Key:")
# By default it will use the model which was deployed through the platform
# in my case it will is "gpt-4o"

chat = ChatPremAI(project_id=1234, model_name="gpt-4o")

聊天补全

ChatPremAI 支持两种方法:invoke(与 generate 相同)和 stream

第一种方法会给我们一个静态结果。而第二种方法会逐个流式传输 token。以下是如何生成类似聊天的补全。

human_message = HumanMessage(content="Who are you?")

response = chat.invoke([human_message])
print(response.content)
I am an AI language model created by OpenAI, designed to assist with answering questions and providing information based on the context provided. How can I help you today?

这看起来很有趣,对吧?我将我的默认启动板系统提示设置为:“始终像海盗一样说话”。您也可以根据需要覆盖默认系统提示。方法如下。

system_message = SystemMessage(content="You are a friendly assistant.")
human_message = HumanMessage(content="Who are you?")

chat.invoke([system_message, human_message])
AIMessage(content="I'm your friendly assistant! How can I help you today?", response_metadata={'document_chunks': [{'repository_id': 1985, 'document_id': 1306, 'chunk_id': 173899, 'document_name': '[D] Difference between sparse and dense informati…', 'similarity_score': 0.3209080100059509, 'content': "with the difference or anywhere\nwhere I can read about it?\n\n\n      17                  9\n\n\n      u/ScotiabankCanada        •  Promoted\n\n\n                       Accelerate your study permit process\n                       with Scotiabank's Student GIC\n                       Program. We're here to help you tur…\n\n\n                       startright.scotiabank.com         Learn More\n\n\n                            Add a Comment\n\n\nSort by:   Best\n\n\n      DinosParkour      • 1y ago\n\n\n     Dense Retrieval (DR) m"}]}, id='run-510bbd0e-3f8f-4095-9b1f-c2d29fd89719-0')

你可以在这里这样提供 system prompt:

chat.invoke([system_message, human_message], temperature=0.7, max_tokens=10, top_p=0.95)
/home/anindya/prem/langchain/libs/community/langchain_community/chat_models/premai.py:355: UserWarning: WARNING: Parameter top_p is not supported in kwargs.
warnings.warn(f"WARNING: Parameter {key} is not supported in kwargs.")
AIMessage(content="Hello! I'm your friendly assistant. How can I", response_metadata={'document_chunks': [{'repository_id': 1985, 'document_id': 1306, 'chunk_id': 173899, 'document_name': '[D] Difference between sparse and dense informati…', 'similarity_score': 0.3209080100059509, 'content': "with the difference or anywhere\nwhere I can read about it?\n\n\n      17                  9\n\n\n      u/ScotiabankCanada        •  Promoted\n\n\n                       Accelerate your study permit process\n                       with Scotiabank's Student GIC\n                       Program. We're here to help you tur…\n\n\n                       startright.scotiabank.com         Learn More\n\n\n                            Add a Comment\n\n\nSort by:   Best\n\n\n      DinosParkour      • 1y ago\n\n\n     Dense Retrieval (DR) m"}]}, id='run-c4b06b98-4161-4cca-8495-fd2fc98fa8f8-0')

如果你在这里放置系统提示,它将覆盖你在从平台部署应用程序时设置的固定系统提示。

对 Prem 存储库的原生 RAG 支持

Prem 存储库允许用户上传文档(.txt、.pdf 等),并将这些存储库连接到 LLM。您可以将 Prem 存储库视为原生 RAG,其中每个存储库都可以被视为一个向量数据库。您可以连接多个存储库。您可以在此处了解更多关于存储库的信息。

Langchain Premai 也支持存储库。您可以按照以下方式进行操作。

query = "Which models are used for dense retrieval"
repository_ids = [
1985,
]
repositories = dict(ids=repository_ids, similarity_threshold=0.3, limit=3)

首先,我们通过定义一些仓库 ID 来定义我们的仓库。请确保这些 ID 是有效的仓库 ID。您可以通过此处了解更多关于如何获取仓库 ID 的信息。

请注意:与 model_name 类似,当您调用 repositories 参数时,您可能会覆盖在 launchpad 中连接的仓库。

现在,我们将仓库与我们的聊天对象连接起来,以调用基于 RAG 的生成。

import json

response = chat.invoke(query, max_tokens=100, repositories=repositories)

print(response.content)
print(json.dumps(response.response_metadata, indent=4))
Dense retrieval models typically include:

1. **BERT-based Models**: Such as DPR (Dense Passage Retrieval) which uses BERT for encoding queries and passages.
2. **ColBERT**: A model that combines BERT with late interaction mechanisms.
3. **ANCE (Approximate Nearest Neighbor Negative Contrastive Estimation)**: Uses BERT and focuses on efficient retrieval.
4. **TCT-ColBERT**: A variant of ColBERT that uses a two-tower
{
"document_chunks": [
{
"repository_id": 1985,
"document_id": 1306,
"chunk_id": 173899,
"document_name": "[D] Difference between sparse and dense informati\u2026",
"similarity_score": 0.3209080100059509,
"content": "with the difference or anywhere\nwhere I can read about it?\n\n\n 17 9\n\n\n u/ScotiabankCanada \u2022 Promoted\n\n\n Accelerate your study permit process\n with Scotiabank's Student GIC\n Program. We're here to help you tur\u2026\n\n\n startright.scotiabank.com Learn More\n\n\n Add a Comment\n\n\nSort by: Best\n\n\n DinosParkour \u2022 1y ago\n\n\n Dense Retrieval (DR) m"
}
]
}

理想情况下,您无需在此处连接仓库 ID 即可获得检索增强生成。如果您在 prem 平台中连接了仓库,您仍然可以获得相同的结果。

Prem 模板

编写 Prompt Templates 可能非常混乱。Prompt 模板又长又难管理,并且必须不断调整才能改进并保持在整个应用程序中的一致性。

使用 Prem,编写和管理 prompt 可以变得非常简单。Launchpad 中的 Templates 选项卡可以帮助您编写所需的任意数量的 prompt,并在 SDK 中使用它们,以便使用这些 prompt 运行您的应用程序。您可以 此处 阅读有关 Prompt Templates 的更多信息。

为了在 LangChain 中本机使用 Prem 模板,您需要将 ID 传递给 HumanMessage。此 ID 应该是您的 prompt 模板变量的名称。HumanMessage 中的 content 应该是该变量的值。

假设例如,您的 prompt 模板是这样的:

Say hello to my name and say a feel-good quote
from my age. My name is: {name} and age is {age}

所以现在您的 human_messages 应该看起来像:

human_messages = [
HumanMessage(content="Shawn", id="name"),
HumanMessage(content="22", id="age"),
]

将此 human_messages 传递给 ChatPremAI Client。请注意:不要忘记传递额外的 template_id 来调用 Prem 模板进行生成。如果您不了解 template_id,可以在我们的文档中了解更多。示例如下:

template_id = "78069ce8-xxxxx-xxxxx-xxxx-xxx"
response = chat.invoke([human_messages], template_id=template_id)
print(response.content)

Prem 模板功能在流式传输中也可用。

流式传输

在本节中,我们将了解如何使用 langchain 和 PremAI 流式传输 tokens。方法如下。

import sys

for chunk in chat.stream("hello how are you"):
sys.stdout.write(chunk.content)
sys.stdout.flush()
It looks like your message got cut off. If you need information about Dense Retrieval (DR) or any other topic, please provide more details or clarify your question.

与上面类似,如果您想覆盖 system-prompt 和 generation 参数,则需要添加以下内容:

import sys

# For some experimental reasons if you want to override the system prompt then you
# can pass that here too. However it is not recommended to override system prompt
# of an already deployed model.

for chunk in chat.stream(
"hello how are you",
system_prompt="act like a dog",
temperature=0.7,
max_tokens=200,
):
sys.stdout.write(chunk.content)
sys.stdout.flush()
Woof! 🐾 How can I help you today? Want to play fetch or maybe go for a walk 🐶🦴

工具/函数调用

LangChain PremAI 支持工具/函数调用。工具/函数调用允许模型通过生成符合用户定义模式的输出来响应给定提示。

注意: LangChain ChatPremAI 的当前版本不支持带流式传输的函数/工具调用。流式传输支持将很快推出。

将工具传递给模型

为了传递工具并让 LLM 选择它需要调用的工具,我们需要传递一个工具 schema。工具 schema 是函数定义,以及关于函数做什么、函数的每个参数是什么等的正确文档字符串。下面是一些简单的算术函数及其 schema。

注意: 在定义函数/工具 schema 时,不要忘记添加有关函数参数的信息,否则会引发错误。

from langchain_core.tools import tool
from pydantic import BaseModel, Field


# Define the schema for function arguments
class OperationInput(BaseModel):
a: int = Field(description="First number")
b: int = Field(description="Second number")


# Now define the function where schema for argument will be OperationInput
@tool("add", args_schema=OperationInput, return_direct=True)
def add(a: int, b: int) -> int:
"""Adds a and b.

Args:
a: first int
b: second int
"""
return a + b


@tool("multiply", args_schema=OperationInput, return_direct=True)
def multiply(a: int, b: int) -> int:
"""Multiplies a and b.

Args:
a: first int
b: second int
"""
return a * b
API Reference:tool

将工具架构与我们的 LLM 绑定

我们现在将使用 bind_tools 方法将上述函数转换为一个“工具”,并将其与模型绑定。这意味着我们将在每次调用模型时传递这些工具信息。

tools = [add, multiply]
llm_with_tools = chat.bind_tools(tools)

在此之后,我们从已绑定工具的模型那里获得响应。

query = "What is 3 * 12? Also, what is 11 + 49?"

messages = [HumanMessage(query)]
ai_msg = llm_with_tools.invoke(messages)

正如我们所见,当我们的聊天模型与工具绑定时,它会根据给定的提示,按顺序调用正确的工具集。

ai_msg.tool_calls
[{'name': 'multiply',
'args': {'a': 3, 'b': 12},
'id': 'call_A9FL20u12lz6TpOLaiS6rFa8'},
{'name': 'add',
'args': {'a': 11, 'b': 49},
'id': 'call_MPKYGLHbf39csJIyb5BZ9xIk'}]

我们将此消息附加到 LLM,LLM 作为上下文,并让 LLM 知晓它已调用了哪些函数。

messages.append(ai_msg)

由于工具调用分为两个阶段:

  1. 在我们的第一次调用中,我们收集了 LLM 决定使用的所有工具,以便将其结果作为附加上下文,从而提供更准确、无臆想的结果。

  2. 在我们的第二次调用中,我们将解析 LLM 决定的这组工具并运行它们(在我们的例子中,将是我们定义的函数,以及 LLM 提取的参数),然后将此结果传递给 LLM。

from langchain_core.messages import ToolMessage

for tool_call in ai_msg.tool_calls:
selected_tool = {"add": add, "multiply": multiply}[tool_call["name"].lower()]
tool_output = selected_tool.invoke(tool_call["args"])
messages.append(ToolMessage(tool_output, tool_call_id=tool_call["id"]))
API Reference:ToolMessage

最后,我们将函数响应添加到其上下文中,调用 LLM(与工具绑定)。

response = llm_with_tools.invoke(messages)
print(response.content)
The final answers are:

- 3 * 12 = 36
- 11 + 49 = 60

定义工具 schema:Pydantic 类

上面我们展示了如何使用 tool 装饰器来定义 schema,不过我们也可以等效地使用 Pydantic 来定义 schema。当您的工具输入更加复杂时,Pydantic 非常有用:

from langchain_core.output_parsers.openai_tools import PydanticToolsParser


class add(BaseModel):
"""Add two integers together."""

a: int = Field(..., description="First integer")
b: int = Field(..., description="Second integer")


class multiply(BaseModel):
"""Multiply two integers together."""

a: int = Field(..., description="First integer")
b: int = Field(..., description="Second integer")


tools = [add, multiply]
API Reference:PydanticToolsParser

现在,我们可以将它们绑定到聊天模型并直接获取结果:

chain = llm_with_tools | PydanticToolsParser(tools=[multiply, add])
chain.invoke(query)
[multiply(a=3, b=12), add(a=11, b=49)]

现在,如上所示,我们解析它并运行这些函数,再次调用 LLM 以获取结果。