歡迎來到將自訂副駕駛整合到 OpenBB 終端的範例儲存庫。
該儲存庫提供了建立您自己的自訂副駕駛並將其添加到 OpenBB Copilot 所需的一切。
以下是您可能想要建立自己的副駕駛的一些常見原因:
若要整合可從 OpenBB 終端與之互動的自訂 Copilot,您需要建立終端可向其發出請求的後端 API。
您的自訂 copilot API 將使用伺服器發送的事件 (SSE) 進行回應。
注意:如果您希望快速入門,我們建議運行此存儲庫中包含的示例副駕駛之一,並將其作為自定義副駕駛添加到OpenBB 終端(每個示例副駕駛都包含有關如何運行它們的說明)。克隆和修改範例副駕駛是建立自訂副駕駛的好方法。
要理解的最重要的概念是副駕駛協議是無狀態的。這意味著從 OpenBB 終端到副駕駛的每個請求都將在請求負載中包含所有先前的訊息(例如 AI 完成、人工訊息、函數呼叫和函數呼叫結果)。
這表示您的自訂 copilot 不需要在請求之間維護任何狀態。它應該簡單地使用請求負載來產生回應。
OpenBB 終端僅負責維護會話狀態,並將回應附加到請求負載中的messages
陣列中。
OpenBB 終端機將向copilots.json
檔案中定義的query
端點發出 POST 請求(稍後將詳細介紹)。此請求的有效負載將包含當前對話的訊息、任何明確新增的上下文、有關當前活動儀表板上的小部件的資訊、要檢索的 URL 等資料。
您必須實現的查詢請求架構的核心如下:
{
"messages" : [ # <-- the chat messages between the user and the copilot (including function calls and results)
{
"role" : "human" , # <-- each message has a role: "human", "ai", or "tool"
"content" : "Hi there." # <-- the content of the message
}
],
"context" : [ # <-- explicitly added context by the user (optional)
{
"uuid" : "3fa85f64-5717-4562-b3fc-2c963f66afa6" , # <-- the UUID of the widget
"name" : "<widget name>" , # <-- the name of the widget
"description" : "<widget description>" , # <-- the description of the widget
"data" : {
"content" : "<data>" # <-- the data of the widget
},
"metadata" : {
"<metadata key>" : "<metadata value>" , # <-- the metadata of the widget
...
}
},
...
],
"widgets" : [ # <-- the widgets currently visible on the active dashboard on Terminal Pro (optional)
{
"uuid" : "3fa85f64-5717-4562-b3fc-2c963f66afa6" , # <-- the UUID of the widget
"name" : "<widget name>" , # <-- the name of the widget
"description" : "<widget description>" , # <-- the description of the widget
"metadata" : {
"<metadata key>" : "<metadata value>" , # <-- the metadata of the widget
...
}
},
...
],
}
我們將在下面更詳細地討論每個欄位。
messages
這是用戶和副駕駛之間的訊息列表。這包括用戶的消息、副駕駛的消息、函數呼叫和函數呼叫結果。每條訊息都有其role
和content
。
最簡單的例子是當不涉及函數呼叫時,它僅由human
和ai
訊息的陣列組成。
OpenBB 終端機會自動將所有傳回的ai
訊息(來自您的 Copilot)附加到任何後續請求的messages
陣列中。
# Only one human message
{
"messages" : [
{
"role" : "human" ,
"content" : "Hi there."
}
],
...
}
# Multiple messages
{
"messages" : [
{
"role" : "human" ,
"content" : "Hi there."
},
{
"role" : "ai" ,
"content" : "Hi there, I'm a copilot. How are you?"
},
{
"role" : "human" ,
"content" : "I'm fine, thank you. What is the weather in Tokyo?"
}
],
...
}
對 Terminal Pro 的函數呼叫(例如檢索小部件資料時)以及這些函數呼叫的結果(包含小部件資料)也包含在messages
數組中。有關函數呼叫的信息,請參閱下面的“函數呼叫”部分。
context
這是一個可選的小部件資料數組,當使用者明確將小部件新增為上下文時,OpenBB 終端將發送該數組。當使用者點擊 OpenBB 終端機中小工具上的「新增為上下文」按鈕時,就會發生這種情況。
context
欄位的工作原理如下:
{
...
" context ": [
{
"uuid" : "3fa85f64-5717-4562-b3fc-2c963f66afa6" , # <-- each widget has a UUID
"name" : "Analyst Estimates" ,
"description" : "Contains analyst estimates for a ticker" ,
"data" : {
"content" : "<data>" # <-- the data of the widget could either be a JSON string or plaintext (you must choose how to handle this in your copilot)
},
"metadata" : { # <-- additional metadata about the widget
"symbol" : "AAPL" ,
"period" : "quarter" ,
"source" : "Financial Modelling Prep" ,
"lastUpdated" : 1728998071322
}
},
{
"uuid" : "8b2e5f79-3a1d-4c9e-b6f8-1e7d2a9c0b3d" , # <-- the context can have multiple widgets
"name" : "Earnings Transcripts" ,
"description" : "Contains earnings transcripts for a ticker" ,
"data" : {
"content" : "<data>" # <-- the data of the widget
},
"metadata" : {
"symbol" : "AAPL" ,
"period" : "quarter" ,
"source" : "Intrinio" ,
"lastUpdated" : 1728998071322
}
},
...
],
...
}
widgets
這是目前在 Terminal Pro 的活動儀表板上可見的一系列小工具。 *只有當您計劃在自訂 copilot中實現函數呼叫(建議但不是必需)時,這才有用,這允許它從 OpenBB 終端上用戶當前活動的儀表板請求小部件資料。
{
...
" widgets ": [
{
"uuid" : "c276369e-e469-4689-b5fe-3f8c76f7c45a" ,
"name" : "Stock Price Quote Widget" ,
"description" : "Contains the current stock price of a ticker" ,
"metadata" : {
"ticker" : "AAPL"
}
},
{
"uuid" : "9f8e7d6c-5b4a-3c2e-1d0f-9e8d7c6b5a4b" ,
"name" : "Financial Ratios Widget" ,
"description" : "Displays key financial ratios for a company" ,
"metadata" : {
"ticker" : "AAPL" ,
"period" : "TTM"
}
},
...
],
...
}
您的自訂副駕駛必須使用伺服器發送事件 (SSE) 回應 OpenBB 終端的請求。
OpenBB 終端機可以處理以下 SSE:
copilotMessageChunk
:用於將串流副駕駛令牌(部分回應)返回 OpenBB 終端。這些響應可以在生成時進行串流傳輸。copilotFunctionCall
:用於請求資料(例如,小工具資料)或執行特定功能。這指示 Terminal Pro 在客戶端採取進一步的操作。只有當您計劃在自訂 copilot 中實作函數呼叫時才需要這樣做。 copilotMessageChunk
訊息塊SSE具有以下格式:
event: copilotMessageChunk
data: {"delta":"H"} # <-- the `data` field must be a JSON object.
delta
必須是字串,但可以是任意長度。我們建議您在從 LLM 收到的每個區塊生成為delta
後立即將其流回。
例如,如果您想流回訊息“Hi!”,您可以發送以下 SSE:
event: copilotMessageChunk
data: {"delta":"H"}
event: copilotMessageChunk
data: {"delta":"i"}
event: copilotMessageChunk
data: {"delta":"!"}
copilotFunctionCall
(僅函數呼叫時需要)函數呼叫SSE具有以下格式:
event: copilotFunctionCall
data: {"function":"get_widget_data","input_arguments":{"widget_uuid":"c276369e-e469-4689-b5fe-3f8c76f7c45a"}}
同樣, data
欄位必須是 JSON 物件。 function
欄位是要呼叫的函數的名稱(目前只支援get_widget_data
), input_arguments
欄位是要傳遞給函數的參數的字典。對於get_widget_data
函數,唯一必要的參數是widget_uuid
,它是要檢索資料的小部件的 UUID(來自請求的widgets
數組中的 UUID 之一)。
透過向您的 copilot 新增函數調用,它將能夠請求 OpenBB 終端中使用者目前活動儀表板上可見的資料。
使用者儀表板上目前可見的所有小部件的清單將發送到請求負載的widgets
數組中的副駕駛。
若要從小部件檢索數據,您的 copilot 應使用copilotFunctionCall
事件進行回應,並指定小工具 UUID:
event: copilotFunctionCall
data: {"function":"get_widget_data","input_arguments":{"widget_uuid":"c276369e-e469-4689-b5fe-3f8c76f7c45a"}}
發出copilotFunctionCall
事件後,您必須關閉連線並等待來自 OpenBB 終端機的新查詢請求。
當收到copilotFunctionCall
事件時,OpenBB 終端將檢索數據,並發起新的查詢請求。這個新的查詢請求將包括原始函數呼叫以及messages
數組中的函數呼叫結果。
{
...
" messages ": [
...
{
"role" : "ai" ,
"content" : "{ " function " : " get_widget_data " , " input_arguments " :{ " widget_uuid " : " c276369e-e469-4689-b5fe-3f8c76f7c45a " }}"
},
{
"role" : "tool" ,
"function" : "get_widget_data" ,
"data" : {
"content" : "<data>"
}
}
]
}
請注意:
messages
數組中。ai
訊息的content
欄位是copilotFunctionCall
事件的data
欄位的逐字字串編碼的JSON 物件(如果您的副駕駛需要的話,這是一種非常有用的機制,用於走私與函數呼叫相關的其他元數據)。目前,OpenBB 終端支援的唯一函數呼叫是get_widget_data
,它從特定小部件檢索資料。
您的自訂副駕駛從 OpenBB 終端收到以下請求:
{
"messages" : [
{
"role" : " human " ,
"content" : " What is the current stock price of AAPL? "
}
],
"widgets" : [
{
"uuid" : " 38181a68-9650-4940-84fb-a3f29c8869f3 " ,
"name" : " Historical Stock Price " ,
"description" : " Historical Stock Price " ,
"metadata" : {
"symbol" : " AAPL " ,
"source" : " Financial Modelling Prep " ,
"lastUpdated" : 1728994470324
}
}
]
}
然後,您解析回應,將訊息格式化為您的 LLM(包括有關哪些小部件可用的資訊)。假設您的副駕駛確定可以使用可用的小部件來回答使用者的查詢,並產生一個函數呼叫來檢索資料。
然後,您的副駕駛會回應以下 SSE 並關閉連線:
event: copilotFunctionCall
data: {"function":"get_widget_data","input_arguments":{"widget_uuid":"38181a68-9650-4940-84fb-a3f29c8869f3"}}
然後,OpenBB 終端將執行指定的函數,並向您的自訂副駕駛發出新的查詢請求:
{
"messages" : [
{
"role" : "human" ,
"content" : "What is the current stock price of AAPL?"
},
{
"role" : "ai" ,
"content" : "{ " function " : " get_widget_data " , " input_arguments " :{ " widget_uuid " : " 38181a68-9650-4940-84fb-a3f29c8869f3 " }}"
},
{
"role" : "tool" ,
"function" : "get_widget_data" ,
"data" : {
"content" : "[{ " date " : " 2024-10-15T00:00:00-04:00 " , " open " :233.61, " high " :237.49, " low " :232.37, " close " :233.85, " volume " :61901688, " vwap " :234.33, " adj_close " :233.85, " change " :0.24, " change_percent " :0.0010274},{ " date " : " 2024-10-14T00:00:00-04:00 " , " open " :228.7, " high " :231.73, " low " :228.6, " close " :231.3, " volume " :39882100, " vwap " :230.0825, " adj_close " :231.3, " change " :2.6, " change_percent " :0.0114},{ " date " : " 2024-10-11T00:00:00-04:00 " , " open " :229.3, " high " :233.2, " low " :228.9, " close " :231.0, " volume " :32581944, " vwap " :231.0333, " adj_close " :231.0, " change " :1.7, " change_percent " :0.0074}, ... ]"
}
}
],
"widgets" : [
{
"uuid" : "38181a68-9650-4940-84fb-a3f29c8869f3" ,
"name" : "Historical Stock Price" ,
"description" : "Historical Stock Price" ,
"metadata" : {
"symbol" : "AAPL" ,
"source" : "Financial Modelling Prep" ,
"lastUpdated" : 1728994470324
}
}
}
然後,您解析回應、處理資料並將訊息格式化為您的法學碩士。我們假設 LLM 然後產生一串標記來回答使用者的查詢。然後使用copilotMessageChunk
SSE 將這些內容串流回使用者:
event: copilotMessageChunk
data: {"delta":"The"}
event: copilotMessageChunk
data: {"delta":" current"}
event: copilotMessageChunk
data: {"delta":" stock"}
event: copilotMessageChunk
data: {"delta":" price"}
event: copilotMessageChunk
data: {"delta":" of"}
event: copilotMessageChunk
data: {"delta":" Apple"}
event: copilotMessageChunk
data: {"delta":" Inc."}
event: copilotMessageChunk
data: {"delta":" (AAPL)"}
event: copilotMessageChunk
data: {"delta":" is"}
event: copilotMessageChunk
data: {"delta":" $150.75."}
copilots.json
)要將自訂 copilot 與 OpenBB 終端集成,您需要設定並提供copilots.json
檔案。此文件定義自訂 copilot 如何與前端連接,包括自訂 copilot 支援哪些功能以及應將請求傳送到何處。
以下是 copilots.json 配置範例:
{
"example_copilot" : { # <-- the ID of your copilot
"name" : "Mistral Example Co. Copilot" , # <-- the display name of your copilot
"description" : "AI-powered financial copilot that uses Mistral Large as its LLM." , # <-- a short description of your copilot
"image" : "<url>" , # <-- a URL to an image icon for your copilot
"hasStreaming" : true , # <-- whether your copilot supports streaming responses via SSEs. This must always be true.
"hasFunctionCalling" : true , # <-- whether your copilot supports function calling
"endpoints" : {
"query" : "<url>" # <-- the URL that Terminal Pro will send requests to. For example, "http://localhost:7777/v1/query"
}
}
}
您的copilots.json
檔案必須在<your-host>/copilots.json
處提供,例如http://localhost:7777/copilots.json
。