Skip to main content

fastllm_core/
echo.rs

1use async_trait::async_trait;
2use autoagents_llm::chat::{ChatMessage, ChatProvider, ChatResponse, StructuredOutputFormat, Tool};
3use autoagents_llm::completion::{CompletionProvider, CompletionRequest, CompletionResponse};
4use autoagents_llm::embedding::EmbeddingProvider;
5use autoagents_llm::error::LLMError;
6use autoagents_llm::models::ModelsProvider;
7use autoagents_llm::{HasConfig, LLMProvider, NoConfig};
8use std::fmt;
9
10#[derive(Debug, Default)]
11pub struct EchoProvider;
12
13#[async_trait]
14impl ChatProvider for EchoProvider {
15    async fn chat_with_tools(
16        &self,
17        messages: &[ChatMessage],
18        _tools: Option<&[Tool]>,
19        _json_schema: Option<StructuredOutputFormat>,
20    ) -> Result<Box<dyn ChatResponse>, LLMError> {
21        Ok(Box::new(EchoResponse {
22            text: messages
23                .last()
24                .map(|message| message.content.clone())
25                .unwrap_or_default(),
26        }))
27    }
28}
29
30#[async_trait]
31impl CompletionProvider for EchoProvider {
32    async fn complete(
33        &self,
34        request: &CompletionRequest,
35        _json_schema: Option<StructuredOutputFormat>,
36    ) -> Result<CompletionResponse, LLMError> {
37        Ok(CompletionResponse {
38            text: request.prompt.clone(),
39        })
40    }
41}
42
43#[async_trait]
44impl EmbeddingProvider for EchoProvider {
45    async fn embed(&self, input: Vec<String>) -> Result<Vec<Vec<f32>>, LLMError> {
46        Ok(input
47            .into_iter()
48            .map(|text| vec![text.len() as f32])
49            .collect())
50    }
51}
52
53impl ModelsProvider for EchoProvider {}
54
55impl LLMProvider for EchoProvider {}
56
57impl HasConfig for EchoProvider {
58    type Config = NoConfig;
59}
60
61#[derive(Debug)]
62struct EchoResponse {
63    text: String,
64}
65
66impl ChatResponse for EchoResponse {
67    fn text(&self) -> Option<String> {
68        Some(self.text.clone())
69    }
70
71    fn tool_calls(&self) -> Option<Vec<autoagents_llm::ToolCall>> {
72        None
73    }
74}
75
76impl fmt::Display for EchoResponse {
77    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
78        formatter.write_str(&self.text)
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[tokio::test]
87    async fn echo_completion_and_embedding_are_deterministic() {
88        let provider = EchoProvider;
89        let completion = provider
90            .complete(&CompletionRequest::new("hello"), None)
91            .await
92            .expect("completion");
93        let embeddings = provider
94            .embed(vec!["abc".to_string(), "abcd".to_string()])
95            .await
96            .expect("embeddings");
97
98        assert_eq!(completion.text, "hello");
99        assert_eq!(embeddings, vec![vec![3.0], vec![4.0]]);
100    }
101}