Commit
Β·
e6163d4
1
Parent(s):
a01e4db
docs: SPEC_16 verified and corrected against codebase
Browse filesAudit findings corrected:
- simple.py: 778 lines (was 761)
- advanced.py: 488 lines (was 400)
- search_handler.py: 219 lines (was ~150)
- OpenAIChatClient: 25 refs across 5 files (now documented with line numbers)
- Anthropic removal: 46 refs across 6 files (now fully scoped)
New sections added:
- Technical Requirements (BaseChatClient abstract methods verified)
- Required Config Changes (gemini_api_key MUST be added)
- Complete file modification list with line numbers
- Verification checklist for implementer
All line counts and imports verified against actual codebase.
docs/specs/SPEC_16_UNIFIED_CHAT_CLIENT_ARCHITECTURE.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
| 4 |
**Priority**: P1 (Architectural Simplification)
|
| 5 |
**Issue**: Updates [#105](https://github.com/The-Obstacle-Is-The-Way/DeepBoner/issues/105), [#109](https://github.com/The-Obstacle-Is-The-Way/DeepBoner/issues/109)
|
| 6 |
**Created**: 2025-12-01
|
|
|
|
| 7 |
|
| 8 |
## Summary
|
| 9 |
|
|
@@ -22,19 +23,19 @@ Eliminate the Simple Mode / Advanced Mode parallel universe by implementing a pl
|
|
| 22 |
```
|
| 23 |
User Query
|
| 24 |
β
|
| 25 |
-
βββ Has API Key? ββYesβββ Advanced Mode (
|
| 26 |
β βββ Microsoft Agent Framework
|
| 27 |
β βββ OpenAIChatClient (hardcoded dependency)
|
| 28 |
β
|
| 29 |
-
βββ No API Key? βββββββββββ Simple Mode (
|
| 30 |
βββ While-loop orchestration
|
| 31 |
βββ Pydantic AI + HuggingFace
|
| 32 |
```
|
| 33 |
|
| 34 |
**Problems:**
|
| 35 |
-
1. **Double Maintenance**: 1,
|
| 36 |
-
2. **Namespace Lock-in**: The Advanced Orchestrator is tightly coupled to `OpenAIChatClient
|
| 37 |
-
3. **Fragmented Chains**: Using Anthropic requires a "
|
| 38 |
4. **Testing Burden**: Two test suites, two CI paths.
|
| 39 |
|
| 40 |
## Proposed Solution: ChatClientFactory
|
|
@@ -99,7 +100,7 @@ def get_chat_client(
|
|
| 99 |
api_key=api_key or settings.openai_api_key,
|
| 100 |
)
|
| 101 |
|
| 102 |
-
# Gemini (High Performance Alternative)
|
| 103 |
if provider == "gemini" or (provider is None and settings.has_gemini_key):
|
| 104 |
from src.clients.gemini import GeminiChatClient
|
| 105 |
return GeminiChatClient(
|
|
@@ -138,23 +139,114 @@ class AdvancedOrchestrator:
|
|
| 138 |
)
|
| 139 |
```
|
| 140 |
|
| 141 |
-
|
| 142 |
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
|
| 150 |
-
###
|
| 151 |
-
- [ ] Remove `Anthropic` references (Issue #110).
|
| 152 |
-
- [ ] (Future) Implement `GeminiChatClient` to support Google's full stack.
|
| 153 |
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
|
| 159 |
## Why This is "Elegant"
|
| 160 |
|
|
@@ -162,8 +254,26 @@ class AdvancedOrchestrator:
|
|
| 162 |
2. **Dependency Injection**: The specific LLM provider is injected, not hardcoded.
|
| 163 |
3. **Full Stack Alignment**: We prioritize providers (OpenAI, Gemini) that own the whole vertical (LLM + Embeddings), reducing environment complexity.
|
| 164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
## References
|
| 166 |
|
| 167 |
- Microsoft Agent Framework: `agent_framework.BaseChatClient`
|
| 168 |
- Gemini API: [Embeddings + LLM](https://ai.google.dev/gemini-api/docs/embeddings)
|
| 169 |
-
- HuggingFace Inference: `huggingface_hub.InferenceClient`
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
**Priority**: P1 (Architectural Simplification)
|
| 5 |
**Issue**: Updates [#105](https://github.com/The-Obstacle-Is-The-Way/DeepBoner/issues/105), [#109](https://github.com/The-Obstacle-Is-The-Way/DeepBoner/issues/109)
|
| 6 |
**Created**: 2025-12-01
|
| 7 |
+
**Last Verified**: 2025-12-01 (line counts and imports verified against codebase)
|
| 8 |
|
| 9 |
## Summary
|
| 10 |
|
|
|
|
| 23 |
```
|
| 24 |
User Query
|
| 25 |
β
|
| 26 |
+
βββ Has API Key? ββYesβββ Advanced Mode (488 lines)
|
| 27 |
β βββ Microsoft Agent Framework
|
| 28 |
β βββ OpenAIChatClient (hardcoded dependency)
|
| 29 |
β
|
| 30 |
+
βββ No API Key? βββββββββββ Simple Mode (778 lines)
|
| 31 |
βββ While-loop orchestration
|
| 32 |
βββ Pydantic AI + HuggingFace
|
| 33 |
```
|
| 34 |
|
| 35 |
**Problems:**
|
| 36 |
+
1. **Double Maintenance**: 1,266 lines across two orchestrator systems.
|
| 37 |
+
2. **Namespace Lock-in**: The Advanced Orchestrator is tightly coupled to `OpenAIChatClient` (25 references across 5 files).
|
| 38 |
+
3. **Fragmented Chains**: Using Anthropic requires a "Frankenstein" chain (Anthropic LLM + OpenAI Embeddings).
|
| 39 |
4. **Testing Burden**: Two test suites, two CI paths.
|
| 40 |
|
| 41 |
## Proposed Solution: ChatClientFactory
|
|
|
|
| 100 |
api_key=api_key or settings.openai_api_key,
|
| 101 |
)
|
| 102 |
|
| 103 |
+
# Gemini (High Performance Alternative) - REQUIRES config.py update first
|
| 104 |
if provider == "gemini" or (provider is None and settings.has_gemini_key):
|
| 105 |
from src.clients.gemini import GeminiChatClient
|
| 106 |
return GeminiChatClient(
|
|
|
|
| 139 |
)
|
| 140 |
```
|
| 141 |
|
| 142 |
+
---
|
| 143 |
|
| 144 |
+
## Technical Requirements
|
| 145 |
+
|
| 146 |
+
### BaseChatClient Protocol (Verified)
|
| 147 |
+
|
| 148 |
+
The `agent_framework.BaseChatClient` requires implementing **2 abstract methods**:
|
| 149 |
+
|
| 150 |
+
```python
|
| 151 |
+
class HuggingFaceChatClient(BaseChatClient):
|
| 152 |
+
"""Adapter for HuggingFace Inference API."""
|
| 153 |
+
|
| 154 |
+
async def _inner_get_response(
|
| 155 |
+
self,
|
| 156 |
+
messages: list[ChatMessage],
|
| 157 |
+
**kwargs
|
| 158 |
+
) -> ChatResponse:
|
| 159 |
+
"""Synchronous response generation."""
|
| 160 |
+
...
|
| 161 |
+
|
| 162 |
+
async def _inner_get_streaming_response(
|
| 163 |
+
self,
|
| 164 |
+
messages: list[ChatMessage],
|
| 165 |
+
**kwargs
|
| 166 |
+
) -> AsyncIterator[ChatResponseUpdate]:
|
| 167 |
+
"""Streaming response generation."""
|
| 168 |
+
...
|
| 169 |
+
```
|
| 170 |
+
|
| 171 |
+
### Required Config Changes
|
| 172 |
+
|
| 173 |
+
**BEFORE implementation**, add to `src/utils/config.py`:
|
| 174 |
+
|
| 175 |
+
```python
|
| 176 |
+
# Settings class additions:
|
| 177 |
+
gemini_api_key: str | None = Field(default=None, description="Google Gemini API key")
|
| 178 |
+
|
| 179 |
+
@property
|
| 180 |
+
def has_gemini_key(self) -> bool:
|
| 181 |
+
"""Check if Gemini API key is available."""
|
| 182 |
+
return bool(self.gemini_api_key)
|
| 183 |
+
```
|
| 184 |
+
|
| 185 |
+
---
|
| 186 |
+
|
| 187 |
+
## Files to Modify (Complete List)
|
| 188 |
|
| 189 |
+
### Category 1: OpenAIChatClient References (25 total)
|
|
|
|
|
|
|
| 190 |
|
| 191 |
+
| File | Lines | Changes Required |
|
| 192 |
+
|------|-------|------------------|
|
| 193 |
+
| `src/orchestrators/advanced.py` | 31, 70, 95, 101, 122 | Replace with `get_chat_client()` |
|
| 194 |
+
| `src/agents/magentic_agents.py` | 4, 17, 29, 58, 70, 117, 129, 161, 173 | Change type hints to `BaseChatClient` |
|
| 195 |
+
| `src/agents/retrieval_agent.py` | 5, 53, 62 | Change type hints to `BaseChatClient` |
|
| 196 |
+
| `src/agents/code_executor_agent.py` | 7, 43, 52 | Change type hints to `BaseChatClient` |
|
| 197 |
+
| `src/utils/llm_factory.py` | 19, 22, 35, 38, 42 | Merge into `clients/factory.py` |
|
| 198 |
+
|
| 199 |
+
### Category 2: Anthropic References (46 total - Issue #110)
|
| 200 |
+
|
| 201 |
+
| File | Refs | Changes Required |
|
| 202 |
+
|------|------|------------------|
|
| 203 |
+
| `src/agent_factory/judges.py` | 10 | Remove Anthropic imports and fallback |
|
| 204 |
+
| `src/utils/config.py` | 10 | Remove `anthropic_api_key`, `anthropic_model`, `has_anthropic_key` |
|
| 205 |
+
| `src/utils/llm_factory.py` | 10 | Remove Anthropic model creation |
|
| 206 |
+
| `src/app.py` | 12 | Remove Anthropic key detection and UI |
|
| 207 |
+
| `src/orchestrators/simple.py` | 2 | Remove Anthropic mentions |
|
| 208 |
+
| `src/agents/hypothesis_agent.py` | 1 | Update comment |
|
| 209 |
+
|
| 210 |
+
### Category 3: Files to Delete (Phase 3)
|
| 211 |
+
|
| 212 |
+
| File | Lines | Reason |
|
| 213 |
+
|------|-------|--------|
|
| 214 |
+
| `src/orchestrators/simple.py` | 778 | Replaced by unified Advanced Mode |
|
| 215 |
+
| `src/tools/search_handler.py` | 219 | Manager agent handles orchestration |
|
| 216 |
+
|
| 217 |
+
**Total deletion: ~997 lines**
|
| 218 |
+
**Total addition: ~400 lines (new clients)**
|
| 219 |
+
**Net: ~600 fewer lines, single architecture**
|
| 220 |
+
|
| 221 |
+
---
|
| 222 |
+
|
| 223 |
+
## Migration Plan
|
| 224 |
+
|
| 225 |
+
### Phase 1: Neutralize Namespace & Add HuggingFace
|
| 226 |
+
- [ ] Add `gemini_api_key` and `has_gemini_key` to `src/utils/config.py`
|
| 227 |
+
- [ ] Create `src/clients/` package
|
| 228 |
+
- [ ] Implement `HuggingFaceChatClient` adapter (~150 lines)
|
| 229 |
+
- [ ] Implement `ChatClientFactory` (~50 lines)
|
| 230 |
+
- [ ] Refactor `AdvancedOrchestrator` to use `get_chat_client()`
|
| 231 |
+
- [ ] Update type hints in `magentic_agents.py`, `retrieval_agent.py`, `code_executor_agent.py`
|
| 232 |
+
- [ ] Merge `llm_factory.py` functionality into `clients/factory.py`
|
| 233 |
+
|
| 234 |
+
### Phase 2: Simplify Provider Chain (Issue #110)
|
| 235 |
+
- [ ] Remove Anthropic from `judges.py` (10 refs)
|
| 236 |
+
- [ ] Remove Anthropic from `config.py` (10 refs)
|
| 237 |
+
- [ ] Remove Anthropic from `llm_factory.py` (10 refs)
|
| 238 |
+
- [ ] Remove Anthropic from `app.py` (12 refs)
|
| 239 |
+
- [ ] Update user-facing strings mentioning Anthropic
|
| 240 |
+
- [ ] (Future) Implement `GeminiChatClient` (~200 lines)
|
| 241 |
+
|
| 242 |
+
### Phase 3: Deprecate Simple Mode (Issue #105)
|
| 243 |
+
- [ ] Update `src/orchestrators/factory.py` to use unified `AdvancedOrchestrator`
|
| 244 |
+
- [ ] Delete `src/orchestrators/simple.py` (778 lines)
|
| 245 |
+
- [ ] Delete `src/tools/search_handler.py` (219 lines)
|
| 246 |
+
- [ ] Update tests to only test Advanced Mode
|
| 247 |
+
- [ ] Archive deleted files to `docs/archive/` for reference
|
| 248 |
+
|
| 249 |
+
---
|
| 250 |
|
| 251 |
## Why This is "Elegant"
|
| 252 |
|
|
|
|
| 254 |
2. **Dependency Injection**: The specific LLM provider is injected, not hardcoded.
|
| 255 |
3. **Full Stack Alignment**: We prioritize providers (OpenAI, Gemini) that own the whole vertical (LLM + Embeddings), reducing environment complexity.
|
| 256 |
|
| 257 |
+
---
|
| 258 |
+
|
| 259 |
+
## Verification Checklist (For Implementer)
|
| 260 |
+
|
| 261 |
+
Before starting implementation, verify:
|
| 262 |
+
|
| 263 |
+
- [x] `agent_framework.BaseChatClient` exists (verified: `agent_framework._clients.BaseChatClient`)
|
| 264 |
+
- [x] Abstract methods: `_inner_get_response`, `_inner_get_streaming_response`
|
| 265 |
+
- [x] `agent_framework.ChatResponse`, `ChatResponseUpdate`, `ChatMessage` importable
|
| 266 |
+
- [x] `settings.has_openai_key` exists (line 118)
|
| 267 |
+
- [ ] `settings.has_gemini_key` **MUST BE ADDED** (does not exist)
|
| 268 |
+
- [ ] `settings.gemini_api_key` **MUST BE ADDED** (does not exist)
|
| 269 |
+
|
| 270 |
+
---
|
| 271 |
+
|
| 272 |
## References
|
| 273 |
|
| 274 |
- Microsoft Agent Framework: `agent_framework.BaseChatClient`
|
| 275 |
- Gemini API: [Embeddings + LLM](https://ai.google.dev/gemini-api/docs/embeddings)
|
| 276 |
+
- HuggingFace Inference: `huggingface_hub.InferenceClient`
|
| 277 |
+
- Issue #105: Deprecate Simple Mode
|
| 278 |
+
- Issue #109: Simplify Provider Architecture
|
| 279 |
+
- Issue #110: Remove Anthropic Provider Support
|