PremAI
PremAI 是一个一体化平台,可简化由生成式 AI 提供支持的强大、生产就绪型应用程序的创建。通过简化开发过程,PremAI 使您能够专注于增强用户体验并推动应用程序的整体增长。您可以在此处快速开始使用我们的平台。
聊天PremAI
此示例介绍了如何使用 LangChain 与不同的聊天模型进行交互ChatPremAI
安装和设置
我们首先安装langchain和premai-sdk.您可以键入以下命令进行安装:
pip install premai langchain
在继续之前,请确保您已在 PremAI 上注册帐户并已创建一个项目。如果没有,请参考 快速入门指南 开始使用 PremAI 平台。创建您的第一个项目并获取您的 API 密钥。
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_community.chat_models import ChatPremAI
在 LangChain 中设置 PremAI 客户端
导入所需的模块后,让我们设置客户端。现在,我们假设我们的project_id是8.但请确保你使用了你的 project-id,否则它会抛出错误。
要将 langchain 与 prem 一起使用,您无需使用我们的 chat-client 传递任何模型名称或设置任何参数。默认情况下,它将使用 LaunchPad 中使用的模型名称和参数。
注意:如果您更改
model或任何其他参数,如temperature或max_tokens在设置客户端时,它将覆盖 LaunchPad 中使用的现有默认配置。
import os
import getpass
if "PREMAI_API_KEY" not in os.environ:
os.environ["PREMAI_API_KEY"] = getpass.getpass("PremAI API Key:")
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)
您可以在此处提供系统提示符,如下所示:
system_message = SystemMessage(content="You are a friendly assistant.")
human_message = HumanMessage(content="Who are you?")
chat.invoke([system_message, human_message])
您还可以在调用模型时更改生成参数。以下是如何做到这一点:
chat.invoke(
[system_message, human_message],
temperature = 0.7, max_tokens = 20, top_p = 0.95
)
如果您要在此处放置系统提示符,那么它将覆盖从平台部署应用程序时修复的系统提示符。
本地存储库的原生 RAG 支持
Prem Repositories 中,它允许用户上传文档(.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 information\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"
}
]
}
因此,这也意味着您在使用 Prem 平台时无需创建自己的 RAG 管道。Prem 使用自己的 RAG 技术为 Retrieval Augmented Generations 提供一流的性能。
理想情况下,您无需在此处连接存储库 ID 即可获取 Retrieval Augmented Generations。如果您在 prem platform 中连接了存储库,您仍然可以获得相同的结果。
流
在本节中,让我们看看如何使用 langchain 和 PremAI 流式传输代币。这是你如何做到的。
import sys
for chunk in chat.stream("hello how are you"):
sys.stdout.write(chunk.content)
sys.stdout.flush()
与上述类似,如果要覆盖 system-prompt 和 generation 参数,则需要添加以下内容:
import sys
for chunk in chat.stream(
"hello how are you",
system_prompt = "You are an helpful assistant", temperature = 0.7, max_tokens = 20
):
sys.stdout.write(chunk.content)
sys.stdout.flush()
这将一个接一个地流式传输代币。
请注意:截至目前,不支持带流媒体的 RAG。但是,我们仍然通过我们的 API 支持它。您可以在此处了解更多信息。
Prem 模板
编写提示模板可能非常混乱。提示模板很长,难以管理,必须不断调整以改进并在整个应用程序中保持一致。
使用 Prem,编写和管理提示非常简单。Launchpad 中的 Templates (模板) 选项卡可帮助您编写所需数量的提示,并在 SDK 中使用它来使您的应用程序使用这些提示运行。您可以在此处阅读有关 Prompt Templates 的更多信息。
要在 LangChain 中原生使用 Prem Templates,您需要将 id 传递给HumanMessage.此 id 应该是 name (名称) 和 Prompt 模板的变量。这content在HumanMessage应该是该变量的值。
例如,如果您的 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 客户端。请注意:不要忘记
将附加的template_id以使用 Prem Templates 调用生成。如果您不知道template_id您可以在我们的 Docs 中了解更多信息。下面是一个示例:
template_id = "78069ce8-xxxxx-xxxxx-xxxx-xxx"
response = chat.invoke([human_message], template_id=template_id)
Prem 模板也可用于 Streaming。
Prem 嵌入
在本节中,我们将介绍如何使用PremEmbeddings与 LangChain 一起使用。让我们从导入我们的模块并设置我们的 API 密钥开始。
import os
import getpass
from langchain_community.embeddings import PremEmbeddings
if os.environ.get("PREMAI_API_KEY") is None:
os.environ["PREMAI_API_KEY"] = getpass.getpass("PremAI API Key:")
我们支持许多最先进的嵌入模型。您可以在此处查看我们支持的 LLM 和嵌入模型列表。现在让我们开始text-embedding-3-largemodel 的实例。.
model = "text-embedding-3-large"
embedder = PremEmbeddings(project_id=8, model=model)
query = "Hello, this is a test query"
query_result = embedder.embed_query(query)
# Let's print the first five elements of the query embedding vector
print(query_result[:5])
设置model_name与 chat 不同,PremAIEmbeddings 的参数是强制性的。
最后,让我们嵌入一些示例文档
documents = [
"This is document1",
"This is document2",
"This is document3"
]
doc_result = embedder.embed_documents(documents)
# Similar to the previous result, let's print the first five element
# of the first document vector
print(doc_result[0][:5])
print(f"Dimension of embeddings: {len(query_result)}")
嵌入尺寸:3072
doc_result[:5]
结果:
[-0.02129288576543331, 0.0008162345038726926, -0.004556538071483374, 0.02918623760342598, -0.02547479420900345]
工具/函数调用
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。
response = llm_with_tools.invoke(messages)
print(response.content)
输出
The final answers are:
- 3 * 12 = 36
- 11 + 49 = 60
定义工具模式:Pydantic 类Optional
上面我们展示了如何使用tooldecorator 来定义模式,但是我们可以等效地使用 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)]
现在,如上所述,我们解析 this 并运行此函数,然后再次调用 LLM 以获取结果。