PremAI
PremAI 是一個多合一平台,可簡化由生成式 AI 驅動的穩健、可投入生產的應用程式的創建。透過簡化開發流程,PremAI 讓您能夠專注於提升使用者體驗並推動應用程式的整體成長。您可以在此處快速開始使用我們的平台。
ChatPremAI
此範例說明如何使用 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
。但請確保您使用您的專案 ID,否則會拋出錯誤。
若要將 langchain 與 prem 搭配使用,您無需傳遞任何模型名稱或使用我們的聊天用戶端設定任何參數。預設情況下,它將使用 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
。
第一個方法將提供我們靜態結果。而第二個方法將逐個串流 token。以下是如何產生類似聊天的完成。
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
)
如果您要在此處放置系統提示,則它將覆寫您從平台部署應用程式時固定的系統提示。
使用 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
時,您可能會覆寫在啟動板中連接的儲存庫。
現在,我們將儲存庫與我們的聊天物件連接,以呼叫基於 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 技術來提供一流的檢索增強生成效能。
理想情況下,您不需要在此處連接儲存庫 ID 即可取得檢索增強生成。如果您已在 prem 平台中連接儲存庫,您仍然可以取得相同的結果。
串流
在本節中,讓我們看看如何使用 langchain 和 PremAI 串流 token。以下是如何執行此操作。
import sys
for chunk in chat.stream("hello how are you"):
sys.stdout.write(chunk.content)
sys.stdout.flush()
與上述類似,如果您想要覆寫系統提示和產生參數,您需要新增以下內容
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()
這將逐個串流 token。
請注意:目前,不支援使用串流的 RAG。但是,我們仍然透過 API 支援它。您可以在此處瞭解更多相關資訊。
Prem 範本
編寫提示範本可能會非常混亂。提示範本很長、難以管理,而且必須不斷調整以改進並在整個應用程式中保持一致。
使用 Prem,編寫和管理提示可以非常容易。 啟動板內的 範本 標籤可協助您編寫所需的任意多個提示,並在 SDK 內部使用它,以使用這些提示執行您的應用程式。您可以在此處閱讀有關提示範本的更多資訊。
若要將 Prem 範本與 LangChain 原生搭配使用,您需要在 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_message], template_id=template_id)
串流也提供 Prem 範本。
Prem 嵌入
在本節中,我們將介紹如何使用 LangChain 的 PremEmbeddings
存取不同的嵌入模型。讓我們先匯入我們的模組並設定我們的 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-large
模型為例。
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])
與聊天不同,對於 PremAIEmbeddings,設定 model_name
引數是強制性的。
最後,讓我們嵌入一些範例文件
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 = llm_with_tools.invoke(messages)
print(response.content)
輸出
The final answers are:
- 3 * 12 = 36
- 11 + 49 = 60
定義工具模式:Pydantic 類別 Optional
上面我們展示了如何使用 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 以獲得結果。