From ff0ea19b48a18e9a1849bd2a653173a3ed4e4560 Mon Sep 17 00:00:00 2001 From: sigoden Date: Wed, 13 Nov 2024 18:24:43 +0800 Subject: [PATCH] fix: invalid request on qianwen multi tool-calls (#993) --- Argcfile.sh | 6 +++--- src/client/bedrock.rs | 5 ++++- src/client/claude.rs | 5 ++++- src/client/cohere.rs | 4 ++-- src/client/ernie.rs | 4 ++-- src/client/openai.rs | 9 +++++++-- src/client/vertexai.rs | 3 ++- src/config/input.rs | 5 ++--- src/function.rs | 25 +++++++++++++++++++++++-- src/serve.rs | 2 +- 10 files changed, 50 insertions(+), 18 deletions(-) diff --git a/Argcfile.sh b/Argcfile.sh index 2c8a830b..daf8c2db 100755 --- a/Argcfile.sh +++ b/Argcfile.sh @@ -86,15 +86,15 @@ OPENAI_COMPATIBLE_PLATFORMS=( \ deepseek,deepseek-chat,https://api.deepseek.com \ fireworks,accounts/fireworks/models/llama-v3p1-8b-instruct,https://api.fireworks.ai/inference/v1 \ github,gpt-4o-mini,https://models.inference.ai.azure.com \ - groq,llama3-8b-8192,https://api.groq.com/openai/v1 \ + groq,llama-3.1-8b-instant,https://api.groq.com/openai/v1 \ hunyuan,hunyuan-large,https://api.hunyuan.cloud.tencent.com/v1 \ lingyiwanwu,yi-large,https://api.lingyiwanwu.com/v1 \ - mistral,open-mistral-nemo,https://api.mistral.ai/v1 \ + mistral,mistral-small-latest,https://api.mistral.ai/v1 \ moonshot,moonshot-v1-8k,https://api.moonshot.cn/v1 \ openrouter,openai/gpt-4o-mini,https://openrouter.ai/api/v1 \ ollama,llama3.1:latest,http://localhost:11434/v1 \ perplexity,llama-3.1-8b-instruct,https://api.perplexity.ai \ - qianwen,qwen-turbo,https://dashscope.aliyuncs.com/compatible-mode/v1 \ + qianwen,qwen-turbo-latest,https://dashscope.aliyuncs.com/compatible-mode/v1 \ siliconflow,meta-llama/Meta-Llama-3.1-8B-Instruct,https://api.siliconflow.cn/v1 \ together,meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo,https://api.together.xyz/v1 \ xai,grok-beta,https://api.x.ai/v1 \ diff --git a/src/client/bedrock.rs b/src/client/bedrock.rs index f7b30196..e1d6c657 100644 --- a/src/client/bedrock.rs +++ b/src/client/bedrock.rs @@ -363,7 +363,10 @@ fn build_chat_completions_body(data: ChatCompletionsData, model: &Model) -> Resu "content": content, })] } - MessageContent::ToolResults((tool_results, text)) => { + MessageContent::ToolResults(results) => { + let ToolResults { + tool_results, text, .. + } = results; let mut assistant_parts = vec![]; let mut user_parts = vec![]; if !text.is_empty() { diff --git a/src/client/claude.rs b/src/client/claude.rs index 7b472a79..0c905b1a 100644 --- a/src/client/claude.rs +++ b/src/client/claude.rs @@ -202,7 +202,10 @@ pub fn claude_build_chat_completions_body( "content": content, })] } - MessageContent::ToolResults((tool_results, text)) => { + MessageContent::ToolResults(results) => { + let ToolResults { + tool_results, text, .. + } = results; let mut assistant_parts = vec![]; let mut user_parts = vec![]; if !text.is_empty() { diff --git a/src/client/cohere.rs b/src/client/cohere.rs index f471e7a0..c5a31f5d 100644 --- a/src/client/cohere.rs +++ b/src/client/cohere.rs @@ -213,8 +213,8 @@ fn build_chat_completions_body(data: ChatCompletionsData, model: &Model) -> Resu .collect(); Some(json!({ "role": role, "message": list.join("\n\n") })) } - MessageContent::ToolResults((results, _)) => { - tool_results = Some(results); + MessageContent::ToolResults(results) => { + tool_results = Some(results.tool_results); None } } diff --git a/src/client/ernie.rs b/src/client/ernie.rs index d7f1ffb8..0c325e57 100644 --- a/src/client/ernie.rs +++ b/src/client/ernie.rs @@ -231,9 +231,9 @@ fn build_chat_completions_body(data: ChatCompletionsData, model: &Model) -> Valu .flat_map(|message| { let Message { role, content } = message; match content { - MessageContent::ToolResults((tool_results, _)) => { + MessageContent::ToolResults(results) => { let mut list = vec![]; - for tool_result in tool_results { + for tool_result in results.tool_results { list.push(json!({ "role": "assistant", "content": format!("Action: {}\nAction Input: {}", tool_result.call.name, tool_result.call.arguments) diff --git a/src/client/openai.rs b/src/client/openai.rs index c4c2b0c6..0f01e36f 100644 --- a/src/client/openai.rs +++ b/src/client/openai.rs @@ -205,8 +205,13 @@ pub fn openai_build_chat_completions_body(data: ChatCompletionsData, model: &Mod .flat_map(|message| { let Message { role, content } = message; match content { - MessageContent::ToolResults((tool_results, text)) => { - if let Some(true) = tool_results.first().map(|v| v.call.id.is_some()) { + MessageContent::ToolResults(results) => { + let ToolResults { + tool_results, + text, + sequence, + } = results; + if !sequence { let tool_calls: Vec<_> = tool_results.iter().map(|tool_result| { json!({ "id": tool_result.call.id, diff --git a/src/client/vertexai.rs b/src/client/vertexai.rs index 7ba205e4..452eb090 100644 --- a/src/client/vertexai.rs +++ b/src/client/vertexai.rs @@ -342,7 +342,8 @@ pub fn gemini_build_chat_completions_body( .collect(); vec![json!({ "role": role, "parts": parts })] }, - MessageContent::ToolResults((tool_results, _)) => { + MessageContent::ToolResults(results) => { + let tool_results = results.tool_results; let model_parts: Vec = tool_results.iter().map(|tool_result| { json!({ "functionCall": { diff --git a/src/config/input.rs b/src/config/input.rs index 54b2bb0b..bc58f321 100644 --- a/src/config/input.rs +++ b/src/config/input.rs @@ -186,10 +186,9 @@ impl Input { pub fn merge_tool_call(mut self, output: String, tool_results: Vec) -> Self { match self.tool_call.as_mut() { Some(exist_tool_results) => { - exist_tool_results.0.extend(tool_results); - exist_tool_results.1 = output; + exist_tool_results.extend(tool_results, output); } - None => self.tool_call = Some((tool_results, output)), + None => self.tool_call = Some(ToolResults::new(tool_results, output)), } self } diff --git a/src/function.rs b/src/function.rs index 517b9eb8..f77467b9 100644 --- a/src/function.rs +++ b/src/function.rs @@ -13,8 +13,6 @@ use std::{ path::{Path, PathBuf}, }; -pub type ToolResults = (Vec, String); - #[cfg(windows)] const PATH_SEP: &str = ";"; #[cfg(not(windows))] @@ -268,6 +266,29 @@ impl ToolCall { } } +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct ToolResults { + pub tool_results: Vec, + pub text: String, + pub sequence: bool, +} + +impl ToolResults { + pub fn new(tool_results: Vec, text: String) -> Self { + Self { + tool_results, + text, + sequence: false, + } + } + + pub fn extend(&mut self, tool_results: Vec, _text: String) { + self.tool_results.extend(tool_results); + self.text.clear(); + self.sequence = true; + } +} + #[cfg(windows)] fn polyfill_cmd_name>(cmd_name: &str, bin_dir: &[T]) -> String { let cmd_name = cmd_name.to_string(); diff --git a/src/serve.rs b/src/serve.rs index 0b4c4757..84e6c870 100644 --- a/src/serve.rs +++ b/src/serve.rs @@ -889,7 +889,7 @@ fn parse_messages(message: Vec) -> Result> { } output.push(Message::new( MessageRole::Assistant, - MessageContent::ToolResults((list, text)), + MessageContent::ToolResults(ToolResults::new(list, text)), )); tool_results = None; } else {