這是一個用 Rust 實現的 Poe API 客戶端庫。它允許您與 Poe API 平台進行互動,發送查詢請求並接收回應。
- 流式接收 bot 回應
- 獲取可用模型列表(支援傳統 API 和 v1/models API)
- 支援工具調用 (Tool Calls)
- 支援檔案上傳與附件傳送
- 支援 XML 格式工具調用(可選功能)
- 靈活的 URL 配置
在您的 Cargo.toml
文件中添加以下依賴:
[dependencies]
poe_api_process = "0.4.5"
或使用 cargo 指令添加:
```bash
cargo add poe_api_process
use poe_api_process::{PoeClient, ChatRequest, ChatMessage, ChatEventType};
use futures_util::StreamExt;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = PoeClient::new(
"Claude-3.7-Sonnet",
"your_access_key",
"https://api.poe.com",
"https://www.quora.com/poe_api/file_upload_3RD_PARTY_POST"
);
let request = ChatRequest {
version: "1.1".to_string(),
r#type: "query".to_string(),
query: vec![ChatMessage {
role: "user".to_string(),
content: "你好".to_string(),
content_type: "text/markdown".to_string(),
attachments: None,
}],
temperature: None,
user_id: String::new(),
conversation_id: String::new(),
message_id: String::new(),
tools: None,
tool_calls: None,
tool_results: None,
logit_bias: None,
stop_sequences: None,
};
let mut stream = client.stream_request(request).await?;
while let Some(response) = stream.next().await {
match response {
Ok(event) => match event.event {
ChatEventType::Text => {
if let Some(data) = event.data {
if let crate::types::ChatResponseData::Text { text } = data {
println!("收到文字: {}", text);
}
}
},
ChatEventType::ReplaceResponse => {
if let Some(data) = event.data {
if let crate::types::ChatResponseData::Text { text } = data {
println!("替換回應: {}", text);
}
}
},
ChatEventType::Error => {
if let Some(data) = event.data {
if let crate::types::ChatResponseData::Error { text, allow_retry } = data {
eprintln!("伺服器錯誤: {}", text);
if allow_retry {
println!("可以重試請求");
}
}
}
},
ChatEventType::Done => {
println!("對話完成");
break;
},
ChatEventType::Json => {
println!("收到 JSON 事件");
},
ChatEventType::File => {
if let Some(data) = event.data {
if let crate::types::ChatResponseData::File(file_data) = data {
println!("收到檔案: {} ({})", file_data.name, file_data.url);
}
}
},
},
Err(e) => eprintln!("錯誤: {}", e),
}
}
Ok(())
}
PS: 原生BOT接口的工具調用只支持少量模型,並且使用格式嚴格,建議使用 XML Feature。
- 工具調用 (Tool Call): 允許 AI 模型請求執行特定的工具或函數。例如,AI 可能需要查詢天氣、搜索網頁或執行計算等操作。
- 工具結果 (Tool Result): 工具執行後返回的結果,將被發送回 AI 模型以繼續對話。
在建立請求時,可以指定可用的工具:
use serde_json::json;
use poe_api_process::{ChatTool, FunctionDefinition, FunctionParameters};
let request = ChatRequest {
// 其他欄位...
tools: Some(vec![ChatTool {
r#type: "function".to_string(),
function: FunctionDefinition {
name: "get_weather".to_string(),
description: "獲取指定城市的天氣資訊".to_string(),
parameters: FunctionParameters {
r#type: "object".to_string(),
properties: json!({
"city": {
"type": "string",
"description": "城市名稱"
}
}),
required: vec!["city".to_string()],
},
},
}]),
// 其他欄位...
};
當 AI 模型返回工具調用時,您可以處理並提供結果:
use poe_api_process::{ChatToolResult, ChatResponseData};
while let Some(response) = stream.next().await {
match response {
Ok(event) => match event.event {
ChatEventType::Json => {
if let Some(ChatResponseData::ToolCalls(tool_calls)) = event.data {
println!("收到工具調用請求: {:?}", tool_calls);
// 處理工具調用
let tool_results = vec![ChatToolResult {
role: "tool".to_string(),
tool_call_id: tool_calls[0].id.clone(),
name: tool_calls[0].function.name.clone(),
content: r#"{"temperature": 25, "condition": "晴天"}"#.to_string(),
}];
// 發送工具結果回 AI
let mut result_stream = client.send_tool_results(
request.clone(),
tool_calls,
tool_results
).await?;
// 處理後續回應...
while let Some(result_response) = result_stream.next().await {
// 處理回應...
}
}
},
// 其他事件處理...
},
Err(e) => eprintln!("錯誤: {}", e),
}
}
啟用 xml 功能可以將工具調用改為 XML 的方式使用,自動化處理XML內容,不需要改動原有代碼:
[dependencies]
poe_api_process = { version = "0.4.5", features = ["xml"] }
本庫支援上傳本地或遠端檔案,並在請求中附加這些檔案:
use poe_api_process::{Attachment, FileUploadRequest};
// 上傳單個本地檔案
let upload_result = client.upload_local_file("path/to/document.pdf", mime_type: None).await?;
println!("檔案已上傳,URL: {}", upload_result.attachment_url);
// 上傳遠端檔案 (通過 URL)
let remote_upload = client.upload_remote_file("https://example.com/document.pdf").await?;
// 批次上傳多個檔案
let batch_results = client.upload_files_batch(vec![
FileUploadRequest::LocalFile { file: "path/to/first.pdf".to_string() , mime_type: None},
FileUploadRequest::RemoteFile { download_url: "https://example.com/second.pdf".to_string() },
]).await?;
// 在請求中附加檔案
let request = ChatRequest {
// 其他欄位...
query: vec![ChatMessage {
role: "user".to_string(),
content: "請分析這份文件".to_string(),
content_type: "text/markdown".to_string(),
attachments: Some(vec![Attachment {
url: upload_result.attachment_url,
content_type: upload_result.mime_type,
}]),
}],
// 其他欄位...
};
use poe_api_process::get_model_list;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 獲取繁體中文版的模型列表
let models = get_model_list(Some("zh-Hant")).await?;
println!("可用模型列表:");
for (index, model) in models.data.iter().enumerate() {
println!("{}. {}", index + 1, model.id);
}
Ok(())
}
use poe_api_process::PoeClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = PoeClient::new(
"Claude-3.7-Sonnet",
"your_access_key",
"https://api.poe.com",
"https://www.quora.com/poe_api/file_upload_3RD_PARTY_POST"
);
// 獲取 v1/models API 的模型列表
let v1_models = client.get_v1_model_list().await?;
println!("v1 API 模型列表:");
for (index, model) in v1_models.data.iter().enumerate() {
println!("{}. {} (創建時間: {})", index + 1, model.id, model.created);
}
Ok(())
}
啟用 trace 功能可以獲得詳細的日誌輸出:
[dependencies]
poe_api_process = { version = "0.4.5", features = ["trace"] }
- PoeClient::new() 現在需要四個參數:
bot_name
、access_key
、poe_base_url
、poe_file_upload_url
- 新增 get_v1_model_list() 方法作為 PoeClient 的實例方法
- 自動處理 URL 末尾斜線正規化
// v0.2.x 版本
let client = PoeClient::new("Claude-3.7-Sonnet", "your_access_key");
// v0.3.0+ 版本
let client = PoeClient::new(
"Claude-3.7-Sonnet",
"your_access_key",
"https://api.poe.com",
"https://www.quora.com/poe_api/file_upload_3RD_PARTY_POST"
);
- 請確保您擁有可使用的 Poe API 訪問密鑰。
- 使用
stream_request
時,請提供有效的 bot 名稱和訪問密鑰。 get_model_list
不需要訪問密鑰,可以直接使用。get_v1_model_list
需要訪問密鑰,並作為 PoeClient 的方法調用。- 檔案上傳功能受到 Poe 平台的檔案大小和類型限制。