feat(adapter/llm): implement AnthropicAdapter
Implements AnthropicAdapter using the anthropic SDK. - Reads ANTHROPIC_API_KEY from env; raises ValueError if missing - resolve_model() looks up capability_map in team.yaml config, falls back to "capable" tier then hard-coded claude-sonnet-4-6 - complete() supports system_prompt, max_tokens (default 4096), and temperature (default 0) via the context dict - Adds PyGithub to requirements.txt (needed by GitHubAdapter) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
"""
|
||||
adapters/llm/anthropic.py
|
||||
Anthropic Claude adapter — Phase 2 stub.
|
||||
Anthropic Claude LLM adapter — Phase 2 implementation.
|
||||
|
||||
TODO (Phase 2):
|
||||
- Implement complete() using the anthropic SDK (anthropic.Anthropic client).
|
||||
- Implement resolve_model() by reading config/team.yaml capability_map.
|
||||
- Handle streaming responses, rate-limit retries, and token counting.
|
||||
- Support system-prompt injection via context["system_prompt"].
|
||||
- Map capability → model using the provider's capability_map config.
|
||||
Uses the ``anthropic`` SDK to call Claude models. Model selection is driven
|
||||
by the capability_map in team.yaml so the adapter stays provider-agnostic in
|
||||
configuration.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
import anthropic
|
||||
|
||||
from adapters.base.llm import LLMAdapter
|
||||
|
||||
|
||||
@@ -18,27 +19,105 @@ class AnthropicAdapter(LLMAdapter):
|
||||
"""
|
||||
LLM adapter for Anthropic Claude models.
|
||||
|
||||
Reads model configuration from config/team.yaml:
|
||||
models.provider: anthropic
|
||||
models.capability_map.reasoning-heavy.anthropic: claude-opus-4-6
|
||||
models.capability_map.capable.anthropic: claude-sonnet-4-6
|
||||
models.capability_map.fast-cheap.anthropic: claude-haiku-3-5
|
||||
Reads model configuration from the loaded team.yaml config dict::
|
||||
|
||||
models:
|
||||
provider: anthropic
|
||||
capability_map:
|
||||
reasoning-heavy:
|
||||
anthropic: claude-opus-4-6
|
||||
capable:
|
||||
anthropic: claude-sonnet-4-6
|
||||
fast-cheap:
|
||||
anthropic: claude-haiku-3-5
|
||||
|
||||
Environment variables
|
||||
---------------------
|
||||
ANTHROPIC_API_KEY : Required. Authenticates with the Anthropic API.
|
||||
"""
|
||||
|
||||
def __init__(self, config: dict) -> None:
|
||||
# TODO (Phase 2): Accept loaded team.yaml config dict.
|
||||
# Extract API key from environment (ANTHROPIC_API_KEY).
|
||||
# Initialise the anthropic.Anthropic() client.
|
||||
raise NotImplementedError("AnthropicAdapter.__init__ is not yet implemented.")
|
||||
"""
|
||||
Initialise the Anthropic adapter.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
config : Loaded team.yaml config dict.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If ANTHROPIC_API_KEY is not set in the environment.
|
||||
"""
|
||||
self._config = config
|
||||
api_key = os.environ.get("ANTHROPIC_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError(
|
||||
"ANTHROPIC_API_KEY environment variable is not set. "
|
||||
"Export it before running the-agency."
|
||||
)
|
||||
self._client = anthropic.Anthropic(api_key=api_key)
|
||||
self._models_cfg: dict = config.get("models", {})
|
||||
|
||||
def complete(self, prompt: str, capability: str, context: dict) -> str:
|
||||
# TODO (Phase 2): Call anthropic client messages.create().
|
||||
# Use resolve_model(capability) to pick the model.
|
||||
# Support context keys: system_prompt, max_tokens, temperature.
|
||||
# Return response text as a plain string.
|
||||
raise NotImplementedError("AnthropicAdapter.complete is not yet implemented.")
|
||||
"""
|
||||
Send a prompt to a Claude model and return the text response.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
prompt : User-role prompt content.
|
||||
capability : One of "reasoning-heavy" | "capable" | "fast-cheap".
|
||||
context : Optional overrides:
|
||||
system_prompt (str) — prepended as the system turn.
|
||||
max_tokens (int) — defaults to 4096.
|
||||
temperature (float) — defaults to 0.
|
||||
|
||||
Returns
|
||||
-------
|
||||
The model's text completion as a plain string.
|
||||
"""
|
||||
model = self.resolve_model(capability)
|
||||
max_tokens: int = context.get("max_tokens", 4096)
|
||||
temperature: float = context.get("temperature", 0)
|
||||
system_prompt: str = context.get("system_prompt", "")
|
||||
|
||||
create_kwargs: dict = {
|
||||
"model": model,
|
||||
"max_tokens": max_tokens,
|
||||
"messages": [{"role": "user", "content": prompt}],
|
||||
}
|
||||
if system_prompt:
|
||||
create_kwargs["system"] = system_prompt
|
||||
if temperature != 0:
|
||||
create_kwargs["temperature"] = temperature
|
||||
|
||||
response = self._client.messages.create(**create_kwargs)
|
||||
return response.content[0].text
|
||||
|
||||
def resolve_model(self, capability: str) -> str:
|
||||
# TODO (Phase 2): Look up capability in team.yaml capability_map.
|
||||
# Fall back to "capable" tier model if capability is unknown.
|
||||
raise NotImplementedError("AnthropicAdapter.resolve_model is not yet implemented.")
|
||||
"""
|
||||
Map a capability string to the Anthropic model identifier.
|
||||
|
||||
Looks up ``config.models.capability_map[capability][provider]``.
|
||||
Falls back to the "capable" tier model if the capability is unknown.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
capability : One of "reasoning-heavy" | "capable" | "fast-cheap".
|
||||
|
||||
Returns
|
||||
-------
|
||||
Anthropic model identifier (e.g. "claude-opus-4-6").
|
||||
"""
|
||||
provider: str = self._models_cfg.get("provider", "anthropic")
|
||||
cap_map: dict = self._models_cfg.get("capability_map", {})
|
||||
|
||||
if capability in cap_map and provider in cap_map[capability]:
|
||||
return cap_map[capability][provider]
|
||||
|
||||
# Fall back to "capable" tier
|
||||
if "capable" in cap_map and provider in cap_map["capable"]:
|
||||
return cap_map["capable"][provider]
|
||||
|
||||
# Hard-coded last resort
|
||||
return "claude-sonnet-4-6"
|
||||
|
||||
@@ -10,6 +10,9 @@ pyyaml
|
||||
# Environment variable management
|
||||
python-dotenv
|
||||
|
||||
# GitHub VCS adapter
|
||||
PyGithub
|
||||
|
||||
# --- stdlib-only (no pip install needed) ---
|
||||
# sqlite3 — blackboard persistence
|
||||
# dataclasses — task_brief schema
|
||||
|
||||
Reference in New Issue
Block a user