Coverage for src/local_deep_research/llm/providers/implementations/anthropic.py: 95%
38 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-03 23:15 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-03 23:15 +0000
1"""Anthropic LLM provider for Local Deep Research."""
3from langchain_anthropic import ChatAnthropic
4from loguru import logger
6from ....config.thread_settings import (
7 get_setting_from_snapshot,
8 NoSettingsContextError,
9)
10from ..openai_base import OpenAICompatibleProvider
13class AnthropicProvider(OpenAICompatibleProvider):
14 """Anthropic provider for Local Deep Research.
16 This is the official Anthropic API provider.
17 """
19 provider_name = "Anthropic"
20 api_key_setting = "llm.anthropic.api_key"
21 default_model = "" # User must explicitly pick a model — no silent fallback
22 default_base_url = "https://api.anthropic.com/v1"
24 # Metadata for auto-discovery
25 provider_key = "ANTHROPIC"
26 company_name = "Anthropic"
27 is_cloud = True
29 @classmethod
30 def create_llm(cls, model_name=None, temperature=0.7, **kwargs):
31 """Factory function for Anthropic LLMs.
33 Args:
34 model_name: Name of the model to use
35 temperature: Model temperature (0.0-1.0)
36 **kwargs: Additional arguments including settings_snapshot
38 Returns:
39 A configured ChatAnthropic instance
41 Raises:
42 ValueError: If API key is not configured
43 """
44 settings_snapshot = kwargs.get("settings_snapshot")
46 # Get API key from settings
47 api_key = get_setting_from_snapshot(
48 cls.api_key_setting,
49 default=None,
50 settings_snapshot=settings_snapshot,
51 )
53 if not api_key:
54 logger.error(f"{cls.provider_name} API key not found in settings")
55 raise ValueError(
56 f"{cls.provider_name} API key not configured. "
57 f"Please set {cls.api_key_setting} in settings."
58 )
60 # Require an explicit model — no silent fallback to a hardcoded default.
61 if not model_name or not model_name.strip():
62 logger.error(f"{cls.provider_name} model name not provided")
63 raise ValueError(
64 f"{cls.provider_name} model not configured. "
65 f"Please set llm.model in settings "
66 f"(e.g. 'claude-3-5-sonnet-20241022')."
67 )
69 # Build Anthropic-specific parameters
70 anthropic_params = {
71 "model": model_name,
72 "anthropic_api_key": api_key,
73 "temperature": temperature,
74 }
76 # Add max_tokens if specified in settings
77 try:
78 max_tokens = get_setting_from_snapshot(
79 "llm.max_tokens",
80 default=None,
81 settings_snapshot=settings_snapshot,
82 )
83 if max_tokens:
84 anthropic_params["max_tokens"] = int(max_tokens)
85 except NoSettingsContextError:
86 pass # Optional parameter
88 logger.info(
89 f"Creating {cls.provider_name} LLM with model: {model_name}, "
90 f"temperature: {temperature}"
91 )
93 return ChatAnthropic(**anthropic_params)
95 @classmethod
96 def is_available(cls, settings_snapshot=None):
97 """Check if this provider is available.
99 Args:
100 settings_snapshot: Optional settings snapshot to use
102 Returns:
103 True if API key is configured, False otherwise
104 """
105 try:
106 # Check if API key is configured
107 api_key = get_setting_from_snapshot(
108 cls.api_key_setting,
109 default=None,
110 settings_snapshot=settings_snapshot,
111 )
112 return bool(api_key and str(api_key).strip())
113 except Exception:
114 return False