🔧 Fix tool calling + capability awareness
Three fixes: 1. OllamaProvider now sends tools[] in native /api/chat requests 2. OllamaProvider parses tool_calls from response (OpenAI-compatible format with function.name, function.arguments) 3. System prompt now lists available tools so LLM knows it can use bash, curl, read/write files — stops saying "I cannot do that"
This commit is contained in:
@@ -196,7 +196,7 @@ impl AgentLoop {
|
|||||||
let mut system_prompt = self.config.system_prompt.clone();
|
let mut system_prompt = self.config.system_prompt.clone();
|
||||||
if !agent_name.is_empty() {
|
if !agent_name.is_empty() {
|
||||||
system_prompt = format!(
|
system_prompt = format!(
|
||||||
"{}\n\n## Your Identity\n- Name: {}\n- Role: {}\n- You are speaking to: {} ({})\n\n## Memory\nYou have a verbatim dialogue log with your user. Use everything from past conversations as context when answering.",
|
"{}\n\n## Your Identity\n- Name: {}\n- Role: {}\n- You are speaking to: {} ({})\n\n## Your Capabilities\nYou have access to tools that let you:\n- Read, write, and edit files\n- Execute shell commands (bash) — use this for curl, git, package managers\n- Search files and directories\n- Use `bash` to run curl for web requests when needed\n\nWhen a user asks you to do something that requires external data, use your tools. Do NOT say you can't do something if you have a tool that can do it.\n\n## Memory\nYou have a verbatim dialogue log with your user. Use everything from past conversations as context when answering.",
|
||||||
system_prompt,
|
system_prompt,
|
||||||
agent_name,
|
agent_name,
|
||||||
if agent_role.is_empty() { "AI Assistant" } else { &agent_role },
|
if agent_role.is_empty() { "AI Assistant" } else { &agent_role },
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ impl Provider for OllamaProvider {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let body = serde_json::json!({
|
let mut body = serde_json::json!({
|
||||||
"model": self.model,
|
"model": self.model,
|
||||||
"messages": messages,
|
"messages": messages,
|
||||||
"stream": false,
|
"stream": false,
|
||||||
@@ -163,6 +163,11 @@ impl Provider for OllamaProvider {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add tools if present (for function calling)
|
||||||
|
if !context.tools.is_empty() {
|
||||||
|
body["tools"] = serde_json::to_value(&context.tools).unwrap_or_default();
|
||||||
|
}
|
||||||
|
|
||||||
let url = format!("{}/api/chat", self.normalized_base_url());
|
let url = format!("{}/api/chat", self.normalized_base_url());
|
||||||
let mut request = self
|
let mut request = self
|
||||||
.client
|
.client
|
||||||
@@ -192,9 +197,21 @@ impl Provider for OllamaProvider {
|
|||||||
.to_string();
|
.to_string();
|
||||||
let finish_reason = data["done_reason"].as_str().unwrap_or("stop").to_string();
|
let finish_reason = data["done_reason"].as_str().unwrap_or("stop").to_string();
|
||||||
|
|
||||||
|
// Parse tool calls from response (qwen3.5 returns OpenAI-compatible format)
|
||||||
|
let tool_calls = data["message"]["tool_calls"].as_array().map(|calls| {
|
||||||
|
calls.iter().map(|tc| {
|
||||||
|
let func = &tc["function"];
|
||||||
|
gyandoot_core::ToolCall {
|
||||||
|
id: tc["id"].as_str().unwrap_or_default().to_string(),
|
||||||
|
name: func["name"].as_str().unwrap_or_default().to_string(),
|
||||||
|
arguments: func["arguments"].clone(),
|
||||||
|
}
|
||||||
|
}).collect()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(ProviderResponse {
|
Ok(ProviderResponse {
|
||||||
content,
|
content,
|
||||||
tool_calls: None,
|
tool_calls,
|
||||||
finish_reason,
|
finish_reason,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user