ChatPremAI
PremAI 是一个一体化平台,可简化由生成式人工智能驱动的强大生产级应用程序的创建过程。通过优化开发流程,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一起使用,您无需传递任何模型名称或使用我们的chat-client设置任何参数。默认情况下,它将使用LaunchPad中使用的模型名称和参数。
Note: If you change the
modelor any other parameters liketemperatureormax_tokenswhile setting the client, it will override existing default configurations, that was used in 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?
上面的内容看起来很有趣,对吧?我将默认的启动系统提示设置为:Always sound like a pirate。如果有需要,你也可以覆盖默认的系统提示。以下是具体操作方法。
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')
If you are going to place system prompt here, then it will override your system prompt that was fixed while deploying the application from the platform.
使用Prem存储库的原生RAG支持
Prem 仓库允许用户上传文档(如 .txt、.pdf 等)并将这些仓库连接到大型语言模型。您可以将 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的信息。
Please note: Similar like
model_namewhen you invoke the argumentrepositories, then you are potentially overriding the repositories connected in the 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"
}
]
}
Ideally, you do not need to connect Repository IDs here to get Retrieval Augmented Generations. You can still get the same result if you have connected the repositories in prem platform.
LangChain模板
编写提示模板可能会非常混乱。提示模板通常很长,难以管理,并且需要不断调整以改进并保持在应用程序中的一致性。
使用Prem,编写和管理提示可以非常简单。在启动板内的模板选项卡可以帮助您编写所需的所有提示,并在SDK中使用这些提示来运行您的应用程序。您可以在此处阅读更多关于提示模板的信息。
要使用Prem模板与LangChain原生集成,您需要传递一个id,即HumanMessage。这个id应该是您的提示模板变量的名称。content在HumanMessage中应该是该变量的值。
比如说,如果你的提示模板是这样的:
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 支持工具/函数调用。工具/函数调用允许模型通过生成符合用户定义模式的输出来响应给定的提示。
- 你可以在这里的文档中详细了解工具调用的所有内容 in our documentation here。
- 你可以从文档的这一部分了解更多关于langchain工具调用的信息。
注意: 当前版本的LangChain ChatPremAI不支持带有流式传输支持的函数/工具调用。流式传输支持以及函数调用功能即将推出。
将工具传递给模型
为了传递工具并让大型语言模型选择需要调用的工具,我们需要传递一个工具模式。工具模式是函数定义以及适当的文档字符串,说明函数的作用、每个参数的含义等。以下是一些带有其模式的简单算术函数。
注意:在定义函数/工具模式时,不要忘记添加有关函数参数的信息,否则会抛出错误。
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以获得结果。