ChatPremAI
PremAI 是一个一体化平台,简化了由生成式 AI 提供支持的强大、可投入生产的应用程序的创建。通过简化开发过程,PremAI 允许您专注于增强用户体验和推动应用程序的整体增长。您可以快速开始使用我们的平台 此处。
此示例介绍了如何使用 LangChain 与使用ChatPremAI
的不同聊天模型进行交互
安装和设置
我们首先安装langchain
和premai-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_id
为8
。但请确保您使用的是您的项目 ID,否则会引发错误。
要将 langchain 与 prem 一起使用,您无需传递任何模型名称或使用我们的聊天客户端设置任何参数。默认情况下,它将使用LaunchPad中使用的模型名称和参数。
注意:如果您在设置客户端时更改了
model
或任何其他参数(如temperature
或max_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
。
第一个将给我们一个静态结果。而第二个将逐个流式传输标记。以下是如何生成类似聊天的完成。
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?
上面看起来很有趣,对吧?我将我的默认 launchpad 系统提示设置为:始终像海盗一样说话
您也可以根据需要覆盖默认的系统提示。以下是如何操作。
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')
您可以在此处提供系统提示,如下所示
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 模板
编写提示模板可能非常混乱。提示模板很长,难以管理,并且必须持续调整以改进并在整个应用程序中保持一致。
使用**Prem**,编写和管理提示变得非常容易。Launchpad内的**模板**选项卡可帮助您编写所需的任意数量的提示,并在 SDK 内部使用这些提示以使您的应用程序使用这些提示运行。您可以在此处阅读有关提示模板的更多信息。
要使用 LangChain 本地使用 Prem 模板,您需要在HumanMessage
中传递一个 ID。此 ID 应为提示模板变量的名称。HumanMessage
中的content
应为此变量的值。
例如,如果您的提示模板如下所示
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 客户端。请注意:不要忘记传递额外的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 流式传输标记。以下是如何操作。
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.
与上面类似,如果要覆盖系统提示和生成参数,则需要添加以下内容
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 选择它需要调用的工具,我们需要传递一个工具模式。工具模式是函数定义以及有关函数的作用、函数的每个参数是什么等的正确文档字符串。以下是一些带有模式的简单算术函数。
注意:在定义函数/工具模式时,不要忘记添加有关函数参数的信息,否则会引发错误。
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
将工具模式与我们的 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了解它已调用了哪些函数。
messages.append(ai_msg)
由于工具调用分两个阶段进行,其中
-
在我们的第一次调用中,我们收集了LLM决定使用的所有工具,以便它可以将结果作为附加上下文,以提供更准确且无幻觉的结果。
-
在我们的第二次调用中,我们将解析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"]))
最后,我们调用与工具绑定的LLM,并在其上下文中添加函数响应。
response = llm_with_tools.invoke(messages)
print(response.content)
The final answers are:
- 3 * 12 = 36
- 11 + 49 = 60
定义工具模式:Pydantic 类
上面我们展示了如何使用tool
装饰器定义模式,但是我们也可以使用Pydantic等效地定义模式。当您的工具输入更复杂时,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]
现在,我们可以将它们绑定到聊天模型并直接获取结果。
chain = llm_with_tools | PydanticToolsParser(tools=[multiply, add])
chain.invoke(query)
[multiply(a=3, b=12), add(a=11, b=49)]
现在,如上所述,我们解析并运行这些函数,并再次调用LLM以获取结果。