use ambi::agent::tool::{StreamFormatter, ToolCallParser};
use ambi::types::config::OpenAIEngineConfig;
use ambi::{Agent, LLMEngineConfig};
use anyhow::Result;
use serde_json::Value;
pub struct XmlToolParser;
impl ToolCallParser for XmlToolParser {
fn get_tags(&self) -> (String, String) {
unimplemented!()
}
fn format_instruction(&self, tools_json: &str) -> String {
format!(
"You can use tools. Call format:\n<tool_call name=\"tool_name\">{{\"args\":{{...}}}}</tool_call>\nAvailable tools:\n{}",
tools_json
)
}
fn parse(&self, text: &str) -> Vec<(String, Value)> {
let mut calls = Vec::new();
let start_tag = "<tool_call name=\"";
let end_tag = "</tool_call>";
let mut current_text = text;
while let Some(start_idx) = current_text.find(start_tag) {
let name_start = start_idx + start_tag.len();
if let Some(quote_idx) = current_text[name_start..].find("\">") {
let tool_name = ¤t_text[name_start..name_start + quote_idx];
let content_start = name_start + quote_idx + 2;
if let Some(end_idx) = current_text[content_start..].find(end_tag) {
let json_str = ¤t_text[content_start..content_start + end_idx];
if let Ok(args) = serde_json::from_str::<Value>(json_str) {
calls.push((tool_name.to_string(), args));
} else {
println!("Error: Invalid JSON arguments for tool '{}'", tool_name);
}
current_text = ¤t_text[content_start + end_idx + end_tag.len()..];
} else {
break;
}
} else {
break;
}
}
calls
}
fn create_stream_formatter(&self) -> Box<dyn StreamFormatter> {
Box::new(ambi::agent::core::formatter::PassThroughFormatter)
}
}
#[tokio::main]
async fn main() -> Result<()> {
let engine_config = LLMEngineConfig::OpenAI(OpenAIEngineConfig {
api_key: "mock-key".to_string(),
base_url: "https://api.openai.com/v1".to_string(),
model_name: "gpt-4o-mini".to_string(),
temp: 0.7,
top_p: 0.9,
});
let mut _agent = Agent::make(engine_config)
.await?
.with_tool_parser(XmlToolParser);
Ok(())
}