Spaces:
Running
Running
Commit
·
506a9c0
1
Parent(s):
d247864
fix: address CodeRabbit Phase 6 review feedback
Browse files- Dockerfile: Add curl for HEALTHCHECK, use specific extras (not --all-extras)
- app.py: Tighten Magentic mode key detection to require OpenAI specifically
- embeddings.py: Move structlog import to module level
- test_embeddings.py: Remove redundant numpy import
- Dockerfile +4 -3
- src/app.py +14 -7
- src/services/embeddings.py +1 -2
- tests/unit/services/test_embeddings.py +0 -2
Dockerfile
CHANGED
|
@@ -4,9 +4,10 @@ FROM python:3.11-slim
|
|
| 4 |
# Set working directory
|
| 5 |
WORKDIR /app
|
| 6 |
|
| 7 |
-
# Install system dependencies
|
| 8 |
RUN apt-get update && apt-get install -y \
|
| 9 |
git \
|
|
|
|
| 10 |
&& rm -rf /var/lib/apt/lists/*
|
| 11 |
|
| 12 |
# Install uv
|
|
@@ -18,8 +19,8 @@ COPY uv.lock .
|
|
| 18 |
COPY src/ src/
|
| 19 |
COPY README.md .
|
| 20 |
|
| 21 |
-
# Install dependencies
|
| 22 |
-
RUN uv sync --frozen --no-dev --
|
| 23 |
|
| 24 |
# Create non-root user BEFORE downloading models
|
| 25 |
RUN useradd --create-home --shell /bin/bash appuser
|
|
|
|
| 4 |
# Set working directory
|
| 5 |
WORKDIR /app
|
| 6 |
|
| 7 |
+
# Install system dependencies (curl needed for HEALTHCHECK)
|
| 8 |
RUN apt-get update && apt-get install -y \
|
| 9 |
git \
|
| 10 |
+
curl \
|
| 11 |
&& rm -rf /var/lib/apt/lists/*
|
| 12 |
|
| 13 |
# Install uv
|
|
|
|
| 19 |
COPY src/ src/
|
| 20 |
COPY README.md .
|
| 21 |
|
| 22 |
+
# Install runtime dependencies only (no dev/test tools)
|
| 23 |
+
RUN uv sync --frozen --no-dev --extra embeddings --extra magentic
|
| 24 |
|
| 25 |
# Create non-root user BEFORE downloading models
|
| 26 |
RUN useradd --create-home --shell /bin/bash appuser
|
src/app.py
CHANGED
|
@@ -72,23 +72,30 @@ async def research_agent(
|
|
| 72 |
yield "Please enter a research question."
|
| 73 |
return
|
| 74 |
|
| 75 |
-
#
|
| 76 |
-
|
|
|
|
| 77 |
|
| 78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
if mode == "magentic" and use_mock:
|
| 80 |
yield (
|
| 81 |
-
"⚠️ **Warning**: Magentic mode requires
|
| 82 |
"Falling back to Mock Simple mode."
|
| 83 |
)
|
| 84 |
mode = "simple"
|
| 85 |
|
| 86 |
-
orchestrator = configure_orchestrator(use_mock=use_mock, mode=mode)
|
| 87 |
-
|
| 88 |
# Run the agent and stream events
|
| 89 |
-
response_parts = []
|
| 90 |
|
| 91 |
try:
|
|
|
|
| 92 |
async for event in orchestrator.run(message):
|
| 93 |
# Format event as markdown
|
| 94 |
event_md = event.to_markdown()
|
|
|
|
| 72 |
yield "Please enter a research question."
|
| 73 |
return
|
| 74 |
|
| 75 |
+
# Decide whether to use real LLMs or mock based on mode and available keys
|
| 76 |
+
has_openai = bool(os.getenv("OPENAI_API_KEY"))
|
| 77 |
+
has_anthropic = bool(os.getenv("ANTHROPIC_API_KEY"))
|
| 78 |
|
| 79 |
+
if mode == "magentic":
|
| 80 |
+
# Magentic currently supports OpenAI only
|
| 81 |
+
use_mock = not has_openai
|
| 82 |
+
else:
|
| 83 |
+
# Simple mode can work with either provider
|
| 84 |
+
use_mock = not (has_openai or has_anthropic)
|
| 85 |
+
|
| 86 |
+
# If magentic mode requested but no OpenAI key, fallback/warn
|
| 87 |
if mode == "magentic" and use_mock:
|
| 88 |
yield (
|
| 89 |
+
"⚠️ **Warning**: Magentic mode requires OpenAI API key. "
|
| 90 |
"Falling back to Mock Simple mode."
|
| 91 |
)
|
| 92 |
mode = "simple"
|
| 93 |
|
|
|
|
|
|
|
| 94 |
# Run the agent and stream events
|
| 95 |
+
response_parts: list[str] = []
|
| 96 |
|
| 97 |
try:
|
| 98 |
+
orchestrator = configure_orchestrator(use_mock=use_mock, mode=mode)
|
| 99 |
async for event in orchestrator.run(message):
|
| 100 |
# Format event as markdown
|
| 101 |
event_md = event.to_markdown()
|
src/services/embeddings.py
CHANGED
|
@@ -8,6 +8,7 @@ import asyncio
|
|
| 8 |
from typing import Any
|
| 9 |
|
| 10 |
import chromadb
|
|
|
|
| 11 |
from sentence_transformers import SentenceTransformer
|
| 12 |
|
| 13 |
from src.utils.models import Evidence
|
|
@@ -143,8 +144,6 @@ class EmbeddingService:
|
|
| 143 |
)
|
| 144 |
except Exception as e:
|
| 145 |
# Log but don't fail entire deduplication for one bad item
|
| 146 |
-
import structlog
|
| 147 |
-
|
| 148 |
structlog.get_logger().warning(
|
| 149 |
"Failed to process evidence in deduplicate",
|
| 150 |
url=evidence.citation.url,
|
|
|
|
| 8 |
from typing import Any
|
| 9 |
|
| 10 |
import chromadb
|
| 11 |
+
import structlog
|
| 12 |
from sentence_transformers import SentenceTransformer
|
| 13 |
|
| 14 |
from src.utils.models import Evidence
|
|
|
|
| 144 |
)
|
| 145 |
except Exception as e:
|
| 146 |
# Log but don't fail entire deduplication for one bad item
|
|
|
|
|
|
|
| 147 |
structlog.get_logger().warning(
|
| 148 |
"Failed to process evidence in deduplicate",
|
| 149 |
url=evidence.citation.url,
|
tests/unit/services/test_embeddings.py
CHANGED
|
@@ -51,8 +51,6 @@ class TestEmbeddingService:
|
|
| 51 |
async def test_batch_embed_efficient(self, mock_sentence_transformer, mock_chroma_client):
|
| 52 |
"""Batch embedding should call encode with list."""
|
| 53 |
# Setup mock for batch return (list of arrays)
|
| 54 |
-
import numpy as np
|
| 55 |
-
|
| 56 |
mock_sentence_transformer.encode.return_value = np.array([[0.1, 0.2], [0.3, 0.4]])
|
| 57 |
|
| 58 |
service = EmbeddingService()
|
|
|
|
| 51 |
async def test_batch_embed_efficient(self, mock_sentence_transformer, mock_chroma_client):
|
| 52 |
"""Batch embedding should call encode with list."""
|
| 53 |
# Setup mock for batch return (list of arrays)
|
|
|
|
|
|
|
| 54 |
mock_sentence_transformer.encode.return_value = np.array([[0.1, 0.2], [0.3, 0.4]])
|
| 55 |
|
| 56 |
service = EmbeddingService()
|