3.1 KiB
Design: Simplify LLM Provider Trait — Single call_llm Method
Date: 2026-03-24
Scope: Collapse LlmProvider trait from 3 methods to 1, unify all provider implementations
Context
The current LlmProvider trait has 3 methods: generate_search_pass (with web search), generate_rewrite_pass (without web search), and supports_web_search. This split was designed for an adaptive pipeline that used provider-native web search tools. The pipeline no longer uses web search tools — all providers now receive the same prompt and return structured JSON. The distinction between search and rewrite passes is artificial and adds unnecessary complexity.
New Trait
#[async_trait]
pub trait LlmProvider: Send + Sync {
fn provider_id(&self) -> &str;
async fn call_llm(
&self,
model: &str,
system_prompt: &str,
user_prompt: &str,
response_schema: &Value,
) -> Result<Value, AppError>;
}
ProviderCapabilities struct removed. supports_web_search() removed.
Provider Implementations
OpenAI
- Uses the Responses API (
POST /v1/responses) exclusively - No
web_search_previewtool — never enabled - Structured output via
text.format.json_schema - Drops the Chat Completions API path entirely (
call_chat_completions_apiremoved) call_responses_apibecomes thecall_llmimplementation (withoutinclude_web_searchparameter)extract_responses_api_contentstays (parses Responses API output format)extract_chat_completions_contentremoved
Gemini
- Uses
generateContentAPI as before - No
googleSearchtool — never enabled - Structured output via
generationConfig.responseSchema build_request_bodysimplified:include_searchparameter removed- Single
call_llmimplementation
Anthropic
- Uses Messages API as before
- No web search tool
call_llmis the single implementation
Caller Impact
All 6+ call sites change from generate_search_pass(...) or generate_rewrite_pass(...) to call_llm(...). Same arguments, just renamed. No logic change.
Files to Modify
- Rewrite:
backend/src/services/llm/mod.rs— new trait, removeProviderCapabilities - Rewrite:
backend/src/services/llm/openai.rs— singlecall_llmvia Responses API, remove Chat Completions path - Rewrite:
backend/src/services/llm/gemini.rs— singlecall_llm, remove web search - Rewrite:
backend/src/services/llm/anthropic.rs— singlecall_llm - Modify:
backend/src/services/llm/factory.rs— update tests (removesupports_web_searchassertions) - Modify:
backend/src/services/synthesis.rs— rename all call sites tocall_llm - Modify:
backend/src/services/source_scraper.rs— rename call site - Modify:
backend/src/handlers/api_keys.rs— rename call site (key test)
What Does NOT Change
Arc<dyn LlmProvider>— factory still returnsArcschema.rs— all schema builders stayprompts.rs— all prompt builders stay- Frontend — no changes
- Database — no changes
- LLM call logging —
log_llm_callworks the same (prompt + response + timing)