llm-model-configの実装

This commit is contained in:
2026-04-19 23:32:14 +09:00
parent e1d672e9c0
commit 230936274b
50 changed files with 1718 additions and 1175 deletions
@@ -20,9 +20,35 @@ mod recorder;
mod scenarios;
use clap::{Parser, ValueEnum};
use llm_worker::llm_client::providers::anthropic::AnthropicClient;
use llm_worker::llm_client::providers::gemini::GeminiClient;
use llm_worker::llm_client::providers::openai::OpenAIClient;
use llm_worker::llm_client::capability::{
CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport,
};
use llm_worker::llm_client::scheme::{
Scheme, anthropic::AnthropicScheme, gemini::GeminiScheme, openai_chat::OpenAIScheme,
};
use llm_worker::llm_client::transport::{HttpTransport, ResolvedAuth};
/// 既定の capability: fixture 記録には cache_control を付けない
/// (既知モデルの静的テーブルを経由すると scheme 毎に自動設定される)。
fn fallback_capability() -> ModelCapability {
ModelCapability {
tool_calling: ToolCallingSupport::Parallel,
structured_output: StructuredOutput::JsonSchema,
reasoning: None,
vision: false,
prompt_caching: CacheStrategy::Auto,
}
}
fn make_transport<S: Scheme>(
scheme: S,
model: &str,
auth: ResolvedAuth,
) -> HttpTransport<S> {
let cap = scheme.capability_for(model).unwrap_or_else(fallback_capability);
let base_url = scheme.default_base_url().to_string();
HttpTransport::new(scheme, model.to_string(), base_url, auth, cap)
}
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
@@ -60,7 +86,11 @@ async fn run_scenario_with_anthropic(
let api_key = std::env::var("ANTHROPIC_API_KEY")
.expect("ANTHROPIC_API_KEY environment variable must be set");
let model = model.as_deref().unwrap_or("claude-sonnet-4-20250514");
let client = AnthropicClient::new(&api_key, model);
let client = make_transport(
AnthropicScheme::new(),
model,
ResolvedAuth::ApiKey(api_key),
);
recorder::record_request(
&client,
@@ -82,7 +112,7 @@ async fn run_scenario_with_openai(
let api_key =
std::env::var("OPENAI_API_KEY").expect("OPENAI_API_KEY environment variable must be set");
let model = model.as_deref().unwrap_or("gpt-4o");
let client = OpenAIClient::new(&api_key, model);
let client = make_transport(OpenAIScheme::new(), model, ResolvedAuth::ApiKey(api_key));
recorder::record_request(
&client,
@@ -101,10 +131,15 @@ async fn run_scenario_with_ollama(
subdir: &str,
model: Option<String>,
) -> Result<(), Box<dyn std::error::Error>> {
use llm_worker::llm_client::providers::ollama::OllamaClient;
// Ollama typically runs local, no key needed or placeholder
let model = model.as_deref().unwrap_or("llama3"); // default example
let client = OllamaClient::new(model); // base_url placeholder, handled by client default
// Ollama = Anthropic scheme + base_url 差し替え + 認証なし
let model = model.as_deref().unwrap_or("llama3");
let client = HttpTransport::new(
AnthropicScheme::new(),
model.to_string(),
"http://localhost:11434".to_string(),
ResolvedAuth::None,
fallback_capability(),
);
recorder::record_request(
&client,
@@ -126,7 +161,7 @@ async fn run_scenario_with_gemini(
let api_key =
std::env::var("GEMINI_API_KEY").expect("GEMINI_API_KEY environment variable must be set");
let model = model.as_deref().unwrap_or("gemini-2.0-flash");
let client = GeminiClient::new(&api_key, model);
let client = make_transport(GeminiScheme::new(), model, ResolvedAuth::ApiKey(api_key));
recorder::record_request(
&client,
@@ -2,7 +2,11 @@
//!
//! Example of cancelling from another thread during streaming
use llm_worker::llm_client::providers::anthropic::AnthropicClient;
use llm_worker::llm_client::capability::{
CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport,
};
use llm_worker::llm_client::scheme::{Scheme, anthropic::AnthropicScheme};
use llm_worker::llm_client::transport::{HttpTransport, ResolvedAuth};
use llm_worker::{Worker, WorkerResult};
use std::time::Duration;
@@ -22,7 +26,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key =
std::env::var("ANTHROPIC_API_KEY").expect("ANTHROPIC_API_KEY environment variable not set");
let client = AnthropicClient::new(&api_key, "claude-sonnet-4-20250514");
let scheme = AnthropicScheme::new();
let model = "claude-sonnet-4-20250514".to_string();
let cap = scheme.capability_for(&model).unwrap_or(ModelCapability {
tool_calling: ToolCallingSupport::Parallel,
structured_output: StructuredOutput::JsonSchema,
reasoning: None,
vision: false,
prompt_caching: CacheStrategy::Auto,
});
let base_url = scheme.default_base_url().to_string();
let client = HttpTransport::new(scheme, model, base_url, ResolvedAuth::ApiKey(api_key), cap);
let worker = Worker::new(client);
println!("🚀 Starting Worker...");
+51 -17
View File
@@ -44,10 +44,11 @@ use llm_worker::{
interceptor::{Interceptor, PostToolAction, ToolResultInfo},
llm_client::{
LlmClient,
providers::{
anthropic::AnthropicClient, gemini::GeminiClient, ollama::OllamaClient,
openai::OpenAIClient,
capability::{CacheStrategy, ModelCapability, StructuredOutput, ToolCallingSupport},
scheme::{
Scheme, anthropic::AnthropicScheme, gemini::GeminiScheme, openai_chat::OpenAIScheme,
},
transport::{HttpTransport, ResolvedAuth},
},
timeline::{Handler, TextBlockEvent, TextBlockKind, ToolUseBlockEvent, ToolUseBlockKind},
};
@@ -327,6 +328,28 @@ fn get_api_key(args: &Args) -> Result<String, String> {
}
/// Create client based on provider
fn default_capability() -> ModelCapability {
ModelCapability {
tool_calling: ToolCallingSupport::Parallel,
structured_output: StructuredOutput::JsonSchema,
reasoning: None,
vision: false,
prompt_caching: CacheStrategy::Auto,
}
}
fn build_transport<S: Scheme>(
scheme: S,
model: String,
auth: ResolvedAuth,
) -> Box<dyn LlmClient> {
let cap = scheme
.capability_for(&model)
.unwrap_or_else(default_capability);
let base_url = scheme.default_base_url().to_string();
Box::new(HttpTransport::new(scheme, model, base_url, auth, cap))
}
fn create_client(args: &Args) -> Result<Box<dyn LlmClient>, String> {
let model = args
.model
@@ -336,21 +359,32 @@ fn create_client(args: &Args) -> Result<Box<dyn LlmClient>, String> {
let api_key = get_api_key(args)?;
match args.provider {
Provider::Anthropic => {
let client = AnthropicClient::new(&api_key, &model);
Ok(Box::new(client))
}
Provider::Gemini => {
let client = GeminiClient::new(&api_key, &model);
Ok(Box::new(client))
}
Provider::Openai => {
let client = OpenAIClient::new(&api_key, &model);
Ok(Box::new(client))
}
Provider::Anthropic => Ok(build_transport(
AnthropicScheme::new(),
model,
ResolvedAuth::ApiKey(api_key),
)),
Provider::Gemini => Ok(build_transport(
GeminiScheme::new(),
model,
ResolvedAuth::ApiKey(api_key),
)),
Provider::Openai => Ok(build_transport(
OpenAIScheme::new(),
model,
ResolvedAuth::ApiKey(api_key),
)),
Provider::Ollama => {
let client = OllamaClient::new(&model);
Ok(Box::new(client))
// Ollama = Anthropic scheme + base_url 差し替え + 認証なし
let scheme = AnthropicScheme::new();
let cap = default_capability();
Ok(Box::new(HttpTransport::new(
scheme,
model,
"http://localhost:11434".to_string(),
ResolvedAuth::None,
cap,
)))
}
}
}