Selamat datang di contoh repositori untuk mengintegrasikan kopilot khusus ke Terminal OpenBB.
Repositori ini menyediakan semua yang Anda butuhkan untuk membangun dan menambahkan kopilot kustom Anda sendiri ke OpenBB Copilot.
Berikut adalah beberapa alasan umum mengapa Anda mungkin ingin membuat kopilot sendiri:
Untuk mengintegrasikan Copilot kustom yang dapat Anda gunakan untuk berinteraksi dari Terminal OpenBB, Anda harus membuat API backend yang dapat diminta oleh Terminal.
API kopilot khusus Anda akan merespons dengan Server-Sent Events (SSEs).
Catatan: Jika Anda ingin memulai dengan cepat, kami sarankan untuk menjalankan salah satu contoh kopilot yang disertakan sebagai bagian dari repositori ini, dan menambahkannya sebagai kopilot khusus ke Terminal OpenBB (setiap contoh kopilot menyertakan instruksi tentang cara menjalankannya). Mengkloning dan memodifikasi contoh kopilot adalah cara terbaik untuk membuat kopilot khusus.
Konsep yang paling penting untuk dipahami adalah bahwa protokol kopilot tidak memiliki kewarganegaraan . Artinya, setiap permintaan dari Terminal OpenBB ke kopilot Anda akan menyertakan semua pesan sebelumnya (seperti penyelesaian AI, pesan manusia, pemanggilan fungsi, dan hasil pemanggilan fungsi) dalam payload permintaan.
Ini berarti kopilot khusus Anda tidak perlu mempertahankan status apa pun di antara permintaan. Itu seharusnya hanya menggunakan payload permintaan untuk menghasilkan respons.
Terminal OpenBB sepenuhnya bertanggung jawab untuk menjaga status percakapan, dan akan menambahkan respons ke rangkaian messages
dalam payload permintaan.
Terminal OpenBB akan membuat permintaan POST ke titik akhir query
yang ditentukan dalam file copilots.json
Anda (lebih lanjut tentang ini nanti). Payload permintaan ini akan berisi data seperti pesan percakapan saat ini, konteks apa pun yang ditambahkan secara eksplisit, informasi tentang widget di dasbor yang sedang aktif, URL yang akan diambil, dan sebagainya.
Inti dari skema permintaan query yang harus Anda terapkan adalah sebagai berikut:
{
"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
...
}
},
...
],
}
Kami akan membahas masing-masing bidang ini secara lebih rinci di bawah.
messages
Ini adalah daftar pesan antara pengguna dan kopilot. Ini mencakup pesan pengguna, pesan kopilot, panggilan fungsi, dan hasil panggilan fungsi. Setiap pesan memiliki role
dan content
.
Contoh paling sederhana adalah ketika tidak ada pemanggilan fungsi yang terlibat, yang hanya terdiri dari serangkaian pesan human
dan ai
.
Terminal OpenBB secara otomatis menambahkan semua pesan return ai
(dari Copilot Anda) ke array messages
dari setiap permintaan tindak lanjut.
# 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?"
}
],
...
}
Panggilan fungsi ke Terminal Pro (misalnya saat mengambil data widget), serta hasil panggilan fungsi tersebut (berisi data widget), juga disertakan dalam larik messages
. Untuk informasi tentang pemanggilan fungsi, lihat bagian "Pemanggilan Fungsi" di bawah.
context
Ini adalah susunan data widget opsional yang akan dikirim oleh Terminal OpenBB ketika widget telah ditambahkan sebagai konteks secara eksplisit oleh pengguna. Hal ini terjadi ketika pengguna mengklik tombol "Tambahkan sebagai Konteks" pada widget di Terminal OpenBB.
Bidang context
berfungsi sebagai berikut:
{
...
" 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
Ini adalah serangkaian widget yang saat ini terlihat di dasbor aktif Terminal Pro. * Ini hanya berguna jika Anda berencana mengimplementasikan pemanggilan fungsi di kopilot kustom Anda (yang disarankan, namun tidak wajib), yang memungkinkannya meminta data widget dari dasbor pengguna yang sedang aktif di Terminal 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"
}
},
...
],
...
}
Kopilot khusus Anda harus merespons permintaan Terminal OpenBB menggunakan Server-Sent Events (SSEs).
Terminal OpenBB dapat memproses SSE berikut:
copilotMessageChunk
: Digunakan untuk mengembalikan token kopilot yang dialirkan (tanggapan sebagian) kembali ke Terminal OpenBB. Respons ini dapat dialirkan saat dihasilkan.copilotFunctionCall
: Digunakan untuk meminta data (misalnya data widget) atau melakukan fungsi tertentu. Ini menginstruksikan Terminal Pro untuk mengambil tindakan lebih lanjut di pihak klien. Ini hanya diperlukan jika Anda berencana mengimplementasikan pemanggilan fungsi di kopilot khusus Anda. copilotMessageChunk
SSE potongan pesan memiliki format berikut:
event: copilotMessageChunk
data: {"delta":"H"} # <-- the `data` field must be a JSON object.
delta
harus berupa string, tetapi panjangnya bisa berapa saja. Kami menyarankan streaming kembali setiap potongan yang Anda terima dari LLM Anda segera setelah itu dihasilkan sebagai delta
.
Misalnya, jika Anda ingin melakukan streaming kembali pesan "Hai!", Anda akan mengirimkan SSE berikut:
event: copilotMessageChunk
data: {"delta":"H"}
event: copilotMessageChunk
data: {"delta":"i"}
event: copilotMessageChunk
data: {"delta":"!"}
copilotFunctionCall
(hanya diperlukan untuk pemanggilan fungsi)Pemanggilan fungsi SSE memiliki format berikut:
event: copilotFunctionCall
data: {"function":"get_widget_data","input_arguments":{"widget_uuid":"c276369e-e469-4689-b5fe-3f8c76f7c45a"}}
Sekali lagi, bidang data
harus berupa objek JSON. Bidang function
adalah nama fungsi yang akan dipanggil (saat ini hanya get_widget_data
yang didukung), dan bidang input_arguments
adalah kamus argumen yang akan diteruskan ke fungsi tersebut. Untuk fungsi get_widget_data
, satu-satunya argumen yang diperlukan adalah widget_uuid
, yang merupakan UUID widget yang datanya akan diambil (dari salah satu UUID dalam array widgets
permintaan).
Dengan menambahkan pemanggilan fungsi ke kopilot Anda, ia akan dapat meminta data yang terlihat di dashboard pengguna yang sedang aktif di Terminal OpenBB.
Daftar semua widget yang saat ini terlihat di dasbor pengguna dikirimkan ke kopilot Anda dalam susunan widgets
payload permintaan.
Untuk mengambil data dari widget, kopilot Anda harus merespons dengan peristiwa copilotFunctionCall
, yang menentukan UUID widget:
event: copilotFunctionCall
data: {"function":"get_widget_data","input_arguments":{"widget_uuid":"c276369e-e469-4689-b5fe-3f8c76f7c45a"}}
Setelah mengeluarkan peristiwa copilotFunctionCall
, Anda harus menutup koneksi dan menunggu permintaan kueri baru dari Terminal OpenBB.
Ketika peristiwa copilotFunctionCall
diterima, Terminal OpenBB akan mengambil data, dan memulai permintaan kueri baru . Permintaan kueri baru ini akan menyertakan pemanggilan fungsi asli, serta hasil pemanggilan fungsi dalam larik 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>"
}
}
]
}
Perhatikan bahwa:
messages
.content
pesan panggilan fungsi ai
adalah objek JSON yang dikodekan string kata demi kata dari bidang data
peristiwa copilotFunctionCall
(ini adalah mekanisme yang sangat berguna untuk menyelundupkan metadata tambahan yang terkait dengan pemanggilan fungsi, jika kopilot Anda memerlukannya). Saat ini, satu-satunya pemanggilan fungsi yang didukung oleh Terminal OpenBB adalah get_widget_data
, yang mengambil data dari widget tertentu.
Kopilot khusus Anda menerima permintaan berikut dari Terminal 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
}
}
]
}
Anda kemudian mengurai responsnya, memformat pesan ke LLM Anda (termasuk informasi tentang widget mana yang tersedia). Anggaplah kopilot Anda menentukan bahwa pertanyaan pengguna dapat dijawab menggunakan widget yang tersedia, dan menghasilkan pemanggilan fungsi untuk mengambil data.
Kopilot Anda kemudian merespons dengan SSE berikut dan menutup koneksi:
event: copilotFunctionCall
data: {"function":"get_widget_data","input_arguments":{"widget_uuid":"38181a68-9650-4940-84fb-a3f29c8869f3"}}
Terminal OpenBB kemudian akan menjalankan fungsi yang ditentukan, dan membuat permintaan kueri baru ke kopilot khusus Anda:
{
"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
}
}
}
Anda kemudian menguraikan respons, memproses data, dan memformat pesan ke LLM Anda. Mari kita asumsikan bahwa LLM kemudian menghasilkan serangkaian token untuk menjawab pertanyaan pengguna. Ini kemudian dialirkan kembali ke pengguna menggunakan 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
) Untuk mengintegrasikan kopilot khusus Anda dengan Terminal OpenBB, Anda perlu mengonfigurasi dan menyajikan file copilots.json
. File ini menentukan bagaimana kopilot khusus Anda terhubung dengan frontend, termasuk fitur mana yang didukung oleh kopilot khusus Anda, dan ke mana permintaan harus dikirim.
Berikut ini contoh konfigurasi 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"
}
}
}
File copilots.json
Anda harus disajikan di <your-host>/copilots.json
, misalnya, http://localhost:7777/copilots.json
.