重构并拆分项目

This commit is contained in:
2026-06-25 17:23:11 +08:00
parent 3476d8cbcb
commit 79ec21bfd4
127 changed files with 1555 additions and 12411 deletions
+17
View File
@@ -0,0 +1,17 @@
[package]
name = "ai"
version = "0.1.0"
edition = "2024"
[dependencies]
common = {path = "../common"}
# ── 异步运行时 ──
tokio = { version = "1.0", features = ["rt-multi-thread", "macros", "sync", "time", "process", "signal", "io-util"] } # 异步运行时核心
# ── HTTP 客户端 ──
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "rustls-tls"] } # HTTP 请求(微信 API + DeepSeek API + 工具调用)
# ── 序列化 ──
serde = { version = "1.0", features = ["derive"] } # 序列化/反序列化
serde_json = "1.0" # JSON 处理
serde_yaml = "0.9" # YAML 解析(工具规范文件)
# ── 时间 ──
chrono = "0.4"
+105
View File
@@ -0,0 +1,105 @@
use crate::toolkit::{call_tools, get_tool};
use common::ai::{
ChatCompletionRequestBody, ChatCompletionRequestExtra, ChatCompletionRequestMessage,
ChatCompletionRequestThinking, ChatCompletionResponseBody,
};
use common::queue::QueueMessage;
pub async fn send_message(
sender: tokio::sync::mpsc::Sender<QueueMessage>,
messages: Vec<ChatCompletionRequestMessage>,
) -> Result<(), reqwest::Error> {
let result = request_llm(messages).await;
match result {
Ok(result) => {
// println!("result:");
for choice in result.unwrap().choices {
let messsage_content = choice.message.content;
let messsage_reasoning = choice.message.reasoning_content.unwrap_or_default();
if !messsage_content.trim().is_empty() || !messsage_content.trim().is_empty() {
sender
.send(QueueMessage::Aissitant(
messsage_reasoning,
messsage_content,
))
.await
.unwrap();
}
match choice.message.tool_calls {
Some(tool_calls) => {
// eprintln!("调用了{}个工具", tool_calls.len());
let queue_message = call_tools(tool_calls).await.unwrap();
if let Some(queue_message) = queue_message {
sender.send(queue_message).await.unwrap();
}
}
None => {
// eprintln!("没有调用工具");
}
}
}
}
Err(err) => {
eprintln!("发送错误:{}", err);
}
}
Ok(())
}
pub async fn request_llm(
messages: Vec<ChatCompletionRequestMessage>,
) -> Result<Option<ChatCompletionResponseBody>, reqwest::Error> {
let client = reqwest::Client::new();
let body = ChatCompletionRequestBody {
model: "deepseek-v4-flash".to_string(),
messages: messages,
stream: false,
tools: get_tool(),
extra_body: Some(ChatCompletionRequestExtra {
thinking: ChatCompletionRequestThinking {
thinking_type: "enabled".to_string(),
},
}),
};
let resp = client
.post("http://100.64.52.162:9807/v1/chat/completions")
.bearer_auth(std::env::var("ROUTER_API_KEY").unwrap())
.json(&body)
.send()
.await;
match resp {
Ok(resp) => {
let status = resp.status();
let text = resp.text().await.unwrap_or_default();
// println!("response:\n{}", text);
if status.is_success() {
let result = serde_json::from_str::<ChatCompletionResponseBody>(&text).unwrap();
return Ok(Some(result));
} else {
eprintln!("HTTP 请求失败");
eprintln!("status: {}", status);
eprintln!("body: {}", text);
}
}
Err(err) => {
eprintln!("请求发送失败: {}", err);
if err.is_timeout() {
eprintln!("原因: 请求超时");
}
if err.is_connect() {
eprintln!("原因: 连接失败");
}
if let Some(url) = err.url() {
eprintln!("url: {}", url);
}
}
}
Ok(None)
}
+2
View File
@@ -0,0 +1,2 @@
pub mod core;
pub mod toolkit;
+62
View File
@@ -0,0 +1,62 @@
use chrono::Local;
use serde_json::error;
use common::{ai::ChatCompletionResponseToolCall, queue::QueueMessage};
pub async fn call_tools(
tools: Vec<ChatCompletionResponseToolCall>,
) -> Result<Option<QueueMessage>, error::Error> {
if let Some(tool) = tools.first() {
if let Some(funcation) = tool.function.as_ref() {
if funcation.name == "query_date_time" {
let date_time = Local::now();
let formatted = date_time.format("%Y-%m-%d %H:%M:%S").to_string();
return Ok(Some(QueueMessage::Tool(
tool.id.clone(),
funcation.name.clone(),
format!("现在时间:{}", formatted),
)));
}
}
}
Ok(None)
}
pub fn get_tool() -> Vec<serde_json::Value> {
return vec![
serde_json::json!({
"type": "function",
"function": {
"name": "query_date_time",
"description": "查看当前时间",
"parameters": {"type": "object", "properties": {}, "required": []}
}
}),
// serde_json::json!({
// "type": "function",
// "function": {
// "name": "query_capabilities",
// "description": "查询所有可用工具的列表、参数格式和用法说明",
// "parameters": {"type": "object", "properties": {}, "required": []}
// }
// }),
// serde_json::json!({
// "type": "function",
// "function": {
// "name": "call_capability",
// "description": "调用指定的工具。先通过 query_capabilities 获取工具名和参数格式",
// "parameters": {
// "type": "object",
// "properties": {
// "name": {"type": "string", "description": "工具名称"},
// "prompt": {
// "type": "object",
// "description": "工具参数对象,如 {\"location\":\"北京\"}"
// }
// },
// "required": ["name", "prompt"]
// }
// }
// }),
];
}