Spaces:
Running
Running
Commit
Β·
82503b1
1
Parent(s):
2eaf2d3
style: integrate CodeRabbit review feedback
Browse files- Add
@pytest
.mark.unit to streaming fix tests
- Simplify API key fallback: nested ternary β (x or y) or None
- Clean up commented-out event handler code in app.py
- Add language specifiers to markdown code blocks (text, bash)
- Remove redundant fallback in judges.py _extract_key_findings
All 138 tests passing.
docs/bugs/P1_MAGENTIC_STREAMING_AND_KEY_PERSISTENCE.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
| 14 |
|
| 15 |
### Symptoms
|
| 16 |
When running Magentic (Advanced) mode, the UI shows hundreds of individual lines like:
|
| 17 |
-
```
|
| 18 |
π‘ STREAMING: Below
|
| 19 |
π‘ STREAMING: is
|
| 20 |
π‘ STREAMING: a
|
|
@@ -157,7 +157,7 @@ Gradio's `ChatInterface` with `additional_inputs` has known issues:
|
|
| 157 |
- Replaced all `OpenAIModel` imports with `OpenAIChatModel` in `src/app.py` and `src/utils/llm_factory.py`.
|
| 158 |
|
| 159 |
### Test Results
|
| 160 |
-
```
|
| 161 |
uv run pytest tests/ -q
|
| 162 |
============================= 138 passed in 20.60s =============================
|
| 163 |
```
|
|
|
|
| 14 |
|
| 15 |
### Symptoms
|
| 16 |
When running Magentic (Advanced) mode, the UI shows hundreds of individual lines like:
|
| 17 |
+
```text
|
| 18 |
π‘ STREAMING: Below
|
| 19 |
π‘ STREAMING: is
|
| 20 |
π‘ STREAMING: a
|
|
|
|
| 157 |
- Replaced all `OpenAIModel` imports with `OpenAIChatModel` in `src/app.py` and `src/utils/llm_factory.py`.
|
| 158 |
|
| 159 |
### Test Results
|
| 160 |
+
```bash
|
| 161 |
uv run pytest tests/ -q
|
| 162 |
============================= 138 passed in 20.60s =============================
|
| 163 |
```
|
src/agent_factory/judges.py
CHANGED
|
@@ -451,12 +451,12 @@ class MockJudgeHandler:
|
|
| 451 |
|
| 452 |
def _extract_key_findings(self, evidence: list[Evidence], max_findings: int = 5) -> list[str]:
|
| 453 |
"""Extract key findings from evidence titles."""
|
| 454 |
-
|
|
|
|
| 455 |
evidence,
|
| 456 |
max_items=max_findings,
|
| 457 |
fallback_message="No specific findings extracted (demo mode)",
|
| 458 |
)
|
| 459 |
-
return findings if findings else ["No specific findings extracted (demo mode)"]
|
| 460 |
|
| 461 |
def _extract_drug_candidates(self, question: str, evidence: list[Evidence]) -> list[str]:
|
| 462 |
"""Extract drug candidates - demo mode returns honest message."""
|
|
|
|
| 451 |
|
| 452 |
def _extract_key_findings(self, evidence: list[Evidence], max_findings: int = 5) -> list[str]:
|
| 453 |
"""Extract key findings from evidence titles."""
|
| 454 |
+
# Helper guarantees non-empty list when fallback_message is provided
|
| 455 |
+
return _extract_titles_from_evidence(
|
| 456 |
evidence,
|
| 457 |
max_items=max_findings,
|
| 458 |
fallback_message="No specific findings extracted (demo mode)",
|
| 459 |
)
|
|
|
|
| 460 |
|
| 461 |
def _extract_drug_candidates(self, question: str, evidence: list[Evidence]) -> list[str]:
|
| 462 |
"""Extract drug candidates - demo mode returns honest message."""
|
src/app.py
CHANGED
|
@@ -127,10 +127,8 @@ async def research_agent(
|
|
| 127 |
yield "Please enter a research question."
|
| 128 |
return
|
| 129 |
|
| 130 |
-
# BUG FIX:
|
| 131 |
-
|
| 132 |
-
# Otherwise, use the persisted state value
|
| 133 |
-
user_api_key = api_key.strip() if api_key else api_key_state.strip() if api_key_state else None
|
| 134 |
|
| 135 |
# Check available keys
|
| 136 |
has_openai = bool(os.getenv("OPENAI_API_KEY"))
|
|
@@ -267,14 +265,8 @@ def create_demo() -> tuple[gr.ChatInterface, gr.Accordion]:
|
|
| 267 |
],
|
| 268 |
)
|
| 269 |
|
| 270 |
-
#
|
| 271 |
-
#
|
| 272 |
-
# When examples are clicked (and only modify first 2 args), state remains.
|
| 273 |
-
# Note: This requires a Blocks context, which ChatInterface doesn't expose easily here.
|
| 274 |
-
# However, by removing the empty strings from the examples list above,
|
| 275 |
-
# we prevent the API key from being overwritten in the first place,
|
| 276 |
-
# so the api_key textbox retains its value, and research_agent receives it directly.
|
| 277 |
-
# api_key_input.change(lambda x: x, inputs=api_key_input, outputs=api_key_state)
|
| 278 |
|
| 279 |
return demo, additional_inputs_accordion
|
| 280 |
|
|
|
|
| 127 |
yield "Please enter a research question."
|
| 128 |
return
|
| 129 |
|
| 130 |
+
# BUG FIX: Prefer freshly-entered key, then persisted state
|
| 131 |
+
user_api_key = (api_key.strip() or api_key_state.strip()) or None
|
|
|
|
|
|
|
| 132 |
|
| 133 |
# Check available keys
|
| 134 |
has_openai = bool(os.getenv("OPENAI_API_KEY"))
|
|
|
|
| 265 |
],
|
| 266 |
)
|
| 267 |
|
| 268 |
+
# API key persists because examples only include [message, mode] columns,
|
| 269 |
+
# so Gradio doesn't overwrite the api_key textbox when examples are clicked.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 270 |
|
| 271 |
return demo, additional_inputs_accordion
|
| 272 |
|
tests/unit/test_streaming_fix.py
CHANGED
|
@@ -7,6 +7,7 @@ import pytest
|
|
| 7 |
from src.utils.models import AgentEvent
|
| 8 |
|
| 9 |
|
|
|
|
| 10 |
@pytest.mark.asyncio
|
| 11 |
async def test_streaming_events_are_buffered_not_spammed():
|
| 12 |
"""
|
|
@@ -92,6 +93,7 @@ async def test_streaming_events_are_buffered_not_spammed():
|
|
| 92 |
app_module.configure_orchestrator = original_configure
|
| 93 |
|
| 94 |
|
|
|
|
| 95 |
@pytest.mark.asyncio
|
| 96 |
async def test_api_key_state_parameter_exists():
|
| 97 |
"""
|
|
|
|
| 7 |
from src.utils.models import AgentEvent
|
| 8 |
|
| 9 |
|
| 10 |
+
@pytest.mark.unit
|
| 11 |
@pytest.mark.asyncio
|
| 12 |
async def test_streaming_events_are_buffered_not_spammed():
|
| 13 |
"""
|
|
|
|
| 93 |
app_module.configure_orchestrator = original_configure
|
| 94 |
|
| 95 |
|
| 96 |
+
@pytest.mark.unit
|
| 97 |
@pytest.mark.asyncio
|
| 98 |
async def test_api_key_state_parameter_exists():
|
| 99 |
"""
|