Files
agcore/src/llm/provider/ollama.rs
T
徐涛 5baa170508 docs: 更新 README feature 表 + 升级指南 + 示例注释 + roadmap 同步
- README 添加 feature 组合表 + 模块级 features 清单 + 升级指南
- 18 个 example 顶部添加 Required features 注释
- roadmap.md 和 roadmap-v0.3.2.md 同步 Phase 26-27 完成状态
- cargo fmt 全量格式化(修复预存格式问题,CI format job 可通过)
2026-07-19 08:18:04 +08:00

73 lines
2.4 KiB
Rust

//! Ollama Provider —— OpenAI-compatible 协议的 newtype 包装,零 API key。
//!
//! 默认 base_url = `http://localhost:11434/v1`,空 api_key 也可工作。
//! 实现方式同 `DeepSeekProvider` / `QwenProvider`,共享 `GenericOpenaiProvider`
//! 的 HTTP/SSE/转换逻辑,仅配置不同。
use std::pin::Pin;
use async_trait::async_trait;
use futures_core::Stream;
use reqwest::Client;
use super::openai::GenericOpenaiProvider;
use crate::llm::error::LlmError;
use crate::llm::types::request_v2::MessageRequest;
use crate::llm::types::response_v2::{MessageResponse, StreamEvent};
use crate::llm::{LlmProvider, ProviderCapabilities};
/// Ollama 本地 Provider —— OpenAI-compatible 协议的 newtype 包装。
///
/// Ollama 在 `localhost:11434` 暴露与 OpenAI 兼容的 `/v1/chat/completions`
/// 接口,因此完全复用 `GenericOpenaiProvider` 的实现。允许空 `api_key`。
pub struct OllamaProvider(pub GenericOpenaiProvider);
impl OllamaProvider {
/// 构造 Ollama Provider。
///
/// - `base_url` 为空时使用默认 `http://localhost:11434/v1`
/// - `api_key` 可为空字符串(Ollama 不校验)
pub fn new(base_url: String, api_key: String, model: String, timeout_secs: u64) -> Self {
let url = if base_url.is_empty() {
"http://localhost:11434/v1".to_string()
} else {
base_url
};
Self(GenericOpenaiProvider::new_with_name(
url,
api_key,
model,
"ollama",
timeout_secs,
))
}
/// 替换默认 HTTP Client(用于 timeout 注入等场景)。
///
/// 与 `OpenaiChatProvider::with_client`、`DeepSeekProvider::with_client`、
/// `QwenProvider::with_client` 签名一致。
pub fn with_client(self, client: Client) -> Self {
Self(self.0.with_client(client))
}
}
#[async_trait]
impl LlmProvider for OllamaProvider {
async fn chat(&self, request: MessageRequest) -> Result<MessageResponse, LlmError> {
self.0.chat(request).await
}
async fn chat_stream(
&self,
request: MessageRequest,
) -> Result<Pin<Box<dyn Stream<Item = Result<StreamEvent, LlmError>> + Send>>, LlmError> {
self.0.chat_stream(request).await
}
fn capabilities(&self) -> ProviderCapabilities {
let mut caps = self.0.capabilities();
caps.provider_name = "ollama";
caps
}
}