Spaces:
Running
Running
Joseph Pollack
commited on
Commit
·
d45d242
1
Parent(s):
e6066ff
implements documentation improvements
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- AUDIO_INPUT_FIX.md +0 -94
- docs/contributing.md → CONTRIBUTING.md +114 -23
- ERROR_FIXES_SUMMARY.md +0 -156
- FILE_OUTPUT_IMPLEMENTATION_PLAN.md +0 -241
- FILE_OUTPUT_VERIFICATION.md +0 -224
- FIX_SUMMARY.md +0 -102
- MULTIMODAL_SETTINGS_IMPLEMENTATION_PLAN.md +0 -386
- MULTIMODAL_SETTINGS_IMPLEMENTATION_SUMMARY.md +0 -157
- Makefile +0 -42
- PDF_REPORT_INTEGRATION.md +0 -134
- README.md +3 -148
- REPORT_WRITING_AGENTS_ANALYSIS.md +0 -189
- SERPER_WEBSEARCH_IMPLEMENTATION_PLAN.md +0 -403
- WEB_SEARCH_TOOL_ASSESSMENT.md +0 -239
- dev/Makefile +0 -51
- dev/__init__.py +1 -0
- docs/MKDOCS_IMPROVEMENTS_ASSESSMENT.md +642 -0
- docs/api/agents.md +45 -85
- docs/api/models.md +21 -23
- docs/api/orchestrators.md +34 -75
- docs/api/services.md +123 -32
- docs/api/tools.md +57 -19
- docs/architecture/agents.md +114 -18
- docs/architecture/graph-orchestration.md +0 -138
- docs/architecture/graph_orchestration.md +54 -10
- docs/architecture/middleware.md +40 -20
- docs/architecture/orchestrators.md +45 -10
- docs/architecture/services.md +36 -19
- docs/architecture/tools.md +26 -12
- docs/architecture/workflow-diagrams.md +4 -17
- docs/configuration/CONFIGURATION.md +0 -557
- docs/contributing/code-quality.md +70 -4
- docs/contributing/code-style.md +39 -1
- docs/contributing/error-handling.md +1 -1
- docs/contributing/implementation-patterns.md +1 -1
- docs/contributing/index.md +121 -16
- docs/contributing/testing.md +68 -4
- docs/getting-started/examples.md +2 -22
- docs/getting-started/installation.md +18 -38
- docs/getting-started/mcp-integration.md +0 -13
- docs/getting-started/quick-start.md +1 -23
- docs/implementation/IMPLEMENTATION_SUMMARY.md +0 -188
- docs/implementation/TOKEN_AUTHENTICATION_REVIEW.md +0 -201
- docs/implementation/TTS_MODAL_IMPLEMENTATION.md +0 -142
- docs/index.md +9 -2
- docs/overview/architecture.md +15 -18
- docs/overview/features.md +36 -19
- docs/overview/quick-start.md +29 -8
- mkdocs.yml +1 -1
- mkdocs.yml.enhanced +166 -0
AUDIO_INPUT_FIX.md
DELETED
|
@@ -1,94 +0,0 @@
|
|
| 1 |
-
# Audio Input Display Fix
|
| 2 |
-
|
| 3 |
-
## Issue
|
| 4 |
-
The audio input (microphone button) was not displaying in the ChatInterface multimodal textbox.
|
| 5 |
-
|
| 6 |
-
## Root Cause
|
| 7 |
-
When `multimodal=True` is set on `gr.ChatInterface`, it should automatically show image and audio buttons. However:
|
| 8 |
-
1. The buttons might be hidden in a dropdown menu
|
| 9 |
-
2. Browser permissions might be blocking microphone access
|
| 10 |
-
3. The `file_types` parameter might not have been explicitly set
|
| 11 |
-
|
| 12 |
-
## Fix Applied
|
| 13 |
-
|
| 14 |
-
### 1. Added `file_types` Parameter
|
| 15 |
-
Explicitly specified which file types are accepted to ensure audio is enabled:
|
| 16 |
-
|
| 17 |
-
```python
|
| 18 |
-
gr.ChatInterface(
|
| 19 |
-
fn=research_agent,
|
| 20 |
-
multimodal=True,
|
| 21 |
-
file_types=["image", "audio", "video"], # Explicitly enable image, audio, and video
|
| 22 |
-
...
|
| 23 |
-
)
|
| 24 |
-
```
|
| 25 |
-
|
| 26 |
-
**File:** `src/app.py` (line 929)
|
| 27 |
-
|
| 28 |
-
### 2. Enhanced UI Description
|
| 29 |
-
Updated the description to make it clearer where to find the audio input:
|
| 30 |
-
|
| 31 |
-
- Added explicit instructions about clicking the 📷 and 🎤 icons
|
| 32 |
-
- Added a tip about looking for icons in the text input box
|
| 33 |
-
- Clarified drag & drop functionality
|
| 34 |
-
|
| 35 |
-
**File:** `src/app.py` (lines 942-948)
|
| 36 |
-
|
| 37 |
-
## How It Works Now
|
| 38 |
-
|
| 39 |
-
1. **Audio Recording Button**: The 🎤 microphone icon should appear in the textbox toolbar when `multimodal=True` is set
|
| 40 |
-
2. **File Upload**: Users can drag & drop audio files or click to upload
|
| 41 |
-
3. **Browser Permissions**: Browser will prompt for microphone access when user clicks the audio button
|
| 42 |
-
|
| 43 |
-
## Testing
|
| 44 |
-
|
| 45 |
-
To verify the fix:
|
| 46 |
-
1. Look for the 🎤 microphone icon in the text input box
|
| 47 |
-
2. Click it to start recording (browser will ask for microphone permission)
|
| 48 |
-
3. Alternatively, drag & drop an audio file into the textbox
|
| 49 |
-
4. Check browser console for any permission errors
|
| 50 |
-
|
| 51 |
-
## Browser Requirements
|
| 52 |
-
|
| 53 |
-
- **Chrome/Edge**: Should work with microphone permissions
|
| 54 |
-
- **Firefox**: Should work with microphone permissions
|
| 55 |
-
- **Safari**: May require additional configuration
|
| 56 |
-
- **HTTPS Required**: Microphone access typically requires HTTPS (or localhost)
|
| 57 |
-
|
| 58 |
-
## Troubleshooting
|
| 59 |
-
|
| 60 |
-
If audio input still doesn't appear:
|
| 61 |
-
|
| 62 |
-
1. **Check Browser Permissions**:
|
| 63 |
-
- Open browser settings
|
| 64 |
-
- Check microphone permissions for the site
|
| 65 |
-
- Ensure microphone is not blocked
|
| 66 |
-
|
| 67 |
-
2. **Check Browser Console**:
|
| 68 |
-
- Open Developer Tools (F12)
|
| 69 |
-
- Look for permission errors or warnings
|
| 70 |
-
- Check for any JavaScript errors
|
| 71 |
-
|
| 72 |
-
3. **Try Different Browser**:
|
| 73 |
-
- Some browsers have stricter permission policies
|
| 74 |
-
- Try Chrome or Firefox if Safari doesn't work
|
| 75 |
-
|
| 76 |
-
4. **Check Gradio Version**:
|
| 77 |
-
- Ensure `gradio>=6.0.0` is installed
|
| 78 |
-
- Update if needed: `pip install --upgrade gradio`
|
| 79 |
-
|
| 80 |
-
5. **HTTPS Requirement**:
|
| 81 |
-
- Microphone access requires HTTPS (or localhost)
|
| 82 |
-
- If deploying, ensure SSL is configured
|
| 83 |
-
|
| 84 |
-
## Additional Notes
|
| 85 |
-
|
| 86 |
-
- The audio button is part of the MultimodalTextbox component
|
| 87 |
-
- It should appear as an icon in the textbox toolbar
|
| 88 |
-
- If it's still not visible, it might be in a dropdown menu (click the "+" or "..." button)
|
| 89 |
-
- The `file_types` parameter ensures audio files are accepted for upload
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/contributing.md → CONTRIBUTING.md
RENAMED
|
@@ -12,7 +12,14 @@ Thank you for your interest in contributing to The DETERMINATOR! This guide will
|
|
| 12 |
- [Key Principles](#key-principles)
|
| 13 |
- [Pull Request Process](#pull-request-process)
|
| 14 |
|
| 15 |
-
> **Note**: Additional sections (Code Style, Error Handling, Testing, Implementation Patterns, Code Quality, and Prompt Engineering) are available as separate pages in the
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
## Git Workflow
|
| 18 |
|
|
@@ -22,9 +29,31 @@ Thank you for your interest in contributing to The DETERMINATOR! This guide will
|
|
| 22 |
- **NEVER** push directly to `main` or `dev` on HuggingFace
|
| 23 |
- GitHub is source of truth; HuggingFace is for deployment
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
## Getting Started
|
| 26 |
|
| 27 |
-
1. **Fork the repository** on GitHub
|
| 28 |
2. **Clone your fork**:
|
| 29 |
|
| 30 |
```bash
|
|
@@ -35,7 +64,8 @@ Thank you for your interest in contributing to The DETERMINATOR! This guide will
|
|
| 35 |
3. **Install dependencies**:
|
| 36 |
|
| 37 |
```bash
|
| 38 |
-
|
|
|
|
| 39 |
```
|
| 40 |
|
| 41 |
4. **Create a feature branch**:
|
|
@@ -48,7 +78,9 @@ Thank you for your interest in contributing to The DETERMINATOR! This guide will
|
|
| 48 |
6. **Run checks**:
|
| 49 |
|
| 50 |
```bash
|
| 51 |
-
|
|
|
|
|
|
|
| 52 |
```
|
| 53 |
|
| 54 |
7. **Commit and push**:
|
|
@@ -57,22 +89,72 @@ Thank you for your interest in contributing to The DETERMINATOR! This guide will
|
|
| 57 |
git commit -m "Description of changes"
|
| 58 |
git push origin yourname-feature-name
|
| 59 |
```
|
|
|
|
| 60 |
8. **Create a pull request** on GitHub
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
## Development Commands
|
| 63 |
|
| 64 |
```bash
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
```
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
## Code Style & Conventions
|
| 77 |
|
| 78 |
### Type Safety
|
|
@@ -118,10 +200,10 @@ result = await loop.run_in_executor(None, cpu_bound_function, args)
|
|
| 118 |
|
| 119 |
### Pre-commit
|
| 120 |
|
| 121 |
-
-
|
| 122 |
- Must pass: lint + typecheck + test-cov
|
| 123 |
-
-
|
| 124 |
-
-
|
| 125 |
|
| 126 |
## Error Handling & Logging
|
| 127 |
|
|
@@ -191,7 +273,7 @@ except httpx.HTTPError as e:
|
|
| 191 |
1. Write failing test in `tests/unit/`
|
| 192 |
2. Implement in `src/`
|
| 193 |
3. Ensure test passes
|
| 194 |
-
4. Run `
|
| 195 |
|
| 196 |
### Test Examples
|
| 197 |
|
|
@@ -212,7 +294,8 @@ async def test_real_pubmed_search():
|
|
| 212 |
|
| 213 |
### Test Coverage
|
| 214 |
|
| 215 |
-
- Run `
|
|
|
|
| 216 |
- Aim for >80% coverage on critical paths
|
| 217 |
- Exclude: `__init__.py`, `TYPE_CHECKING` blocks
|
| 218 |
|
|
@@ -385,7 +468,7 @@ Example:
|
|
| 385 |
|
| 386 |
## Pull Request Process
|
| 387 |
|
| 388 |
-
1. Ensure all checks pass: `
|
| 389 |
2. Update documentation if needed
|
| 390 |
3. Add tests for new features
|
| 391 |
4. Update CHANGELOG if applicable
|
|
@@ -393,11 +476,19 @@ Example:
|
|
| 393 |
6. Address review feedback
|
| 394 |
7. Wait for approval before merging
|
| 395 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
## Questions?
|
| 397 |
|
| 398 |
-
- Open an issue on GitHub
|
| 399 |
-
- Check existing documentation
|
| 400 |
- Review code examples in the codebase
|
| 401 |
|
| 402 |
-
Thank you for contributing to
|
| 403 |
-
|
|
|
|
| 12 |
- [Key Principles](#key-principles)
|
| 13 |
- [Pull Request Process](#pull-request-process)
|
| 14 |
|
| 15 |
+
> **Note**: Additional sections (Code Style, Error Handling, Testing, Implementation Patterns, Code Quality, and Prompt Engineering) are available as separate pages in the [documentation](https://deepcritical.github.io/GradioDemo/contributing/).
|
| 16 |
+
> **Note on Project Names**: "The DETERMINATOR" is the product name, "DeepCritical" is the organization/project name, and "determinator" is the Python package name.
|
| 17 |
+
|
| 18 |
+
## Repository Information
|
| 19 |
+
|
| 20 |
+
- **GitHub Repository**: [`DeepCritical/GradioDemo`](https://github.com/DeepCritical/GradioDemo) (source of truth, PRs, code review)
|
| 21 |
+
- **HuggingFace Space**: [`DataQuests/DeepCritical`](https://huggingface.co/spaces/DataQuests/DeepCritical) (deployment/demo)
|
| 22 |
+
- **Package Name**: `determinator` (Python package name in `pyproject.toml`)
|
| 23 |
|
| 24 |
## Git Workflow
|
| 25 |
|
|
|
|
| 29 |
- **NEVER** push directly to `main` or `dev` on HuggingFace
|
| 30 |
- GitHub is source of truth; HuggingFace is for deployment
|
| 31 |
|
| 32 |
+
### Dual Repository Setup
|
| 33 |
+
|
| 34 |
+
This project uses a dual repository setup:
|
| 35 |
+
|
| 36 |
+
- **GitHub (`DeepCritical/GradioDemo`)**: Source of truth for code, PRs, and code review
|
| 37 |
+
- **HuggingFace (`DataQuests/DeepCritical`)**: Deployment target for the Gradio demo
|
| 38 |
+
|
| 39 |
+
#### Remote Configuration
|
| 40 |
+
|
| 41 |
+
When cloning, set up remotes as follows:
|
| 42 |
+
|
| 43 |
+
```bash
|
| 44 |
+
# Clone from GitHub
|
| 45 |
+
git clone https://github.com/DeepCritical/GradioDemo.git
|
| 46 |
+
cd GradioDemo
|
| 47 |
+
|
| 48 |
+
# Add HuggingFace remote (optional, for deployment)
|
| 49 |
+
git remote add huggingface-upstream https://huggingface.co/spaces/DataQuests/DeepCritical
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
**Important**: Never push directly to `main` or `dev` on HuggingFace. Always work through GitHub PRs. GitHub is the source of truth; HuggingFace is for deployment/demo only.
|
| 53 |
+
|
| 54 |
## Getting Started
|
| 55 |
|
| 56 |
+
1. **Fork the repository** on GitHub: [`DeepCritical/GradioDemo`](https://github.com/DeepCritical/GradioDemo)
|
| 57 |
2. **Clone your fork**:
|
| 58 |
|
| 59 |
```bash
|
|
|
|
| 64 |
3. **Install dependencies**:
|
| 65 |
|
| 66 |
```bash
|
| 67 |
+
uv sync --all-extras
|
| 68 |
+
uv run pre-commit install
|
| 69 |
```
|
| 70 |
|
| 71 |
4. **Create a feature branch**:
|
|
|
|
| 78 |
6. **Run checks**:
|
| 79 |
|
| 80 |
```bash
|
| 81 |
+
uv run ruff check src tests
|
| 82 |
+
uv run mypy src
|
| 83 |
+
uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire
|
| 84 |
```
|
| 85 |
|
| 86 |
7. **Commit and push**:
|
|
|
|
| 89 |
git commit -m "Description of changes"
|
| 90 |
git push origin yourname-feature-name
|
| 91 |
```
|
| 92 |
+
|
| 93 |
8. **Create a pull request** on GitHub
|
| 94 |
|
| 95 |
+
## Package Manager
|
| 96 |
+
|
| 97 |
+
This project uses [`uv`](https://github.com/astral-sh/uv) as the package manager. All commands should be prefixed with `uv run` to ensure they run in the correct environment.
|
| 98 |
+
|
| 99 |
+
### Installation
|
| 100 |
+
|
| 101 |
+
```bash
|
| 102 |
+
# Install uv if you haven't already (recommended: standalone installer)
|
| 103 |
+
# Unix/macOS/Linux:
|
| 104 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 105 |
+
|
| 106 |
+
# Windows (PowerShell):
|
| 107 |
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
| 108 |
+
|
| 109 |
+
# Alternative: pipx install uv
|
| 110 |
+
# Or: pip install uv
|
| 111 |
+
|
| 112 |
+
# Sync all dependencies including dev extras
|
| 113 |
+
uv sync --all-extras
|
| 114 |
+
|
| 115 |
+
# Install pre-commit hooks
|
| 116 |
+
uv run pre-commit install
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
## Development Commands
|
| 120 |
|
| 121 |
```bash
|
| 122 |
+
# Installation
|
| 123 |
+
uv sync --all-extras # Install all dependencies including dev
|
| 124 |
+
uv run pre-commit install # Install pre-commit hooks
|
| 125 |
+
|
| 126 |
+
# Code Quality Checks (run all before committing)
|
| 127 |
+
uv run ruff check src tests # Lint with ruff
|
| 128 |
+
uv run ruff format src tests # Format with ruff
|
| 129 |
+
uv run mypy src # Type checking
|
| 130 |
+
uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire # Tests with coverage
|
| 131 |
+
|
| 132 |
+
# Testing Commands
|
| 133 |
+
uv run pytest tests/unit/ -v -m "not openai" -p no:logfire # Run unit tests (excludes OpenAI tests)
|
| 134 |
+
uv run pytest tests/ -v -m "huggingface" -p no:logfire # Run HuggingFace tests
|
| 135 |
+
uv run pytest tests/ -v -p no:logfire # Run all tests
|
| 136 |
+
uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire # Tests with terminal coverage
|
| 137 |
+
uv run pytest --cov=src --cov-report=html -p no:logfire # Generate HTML coverage report (opens htmlcov/index.html)
|
| 138 |
+
|
| 139 |
+
# Documentation Commands
|
| 140 |
+
uv run mkdocs build # Build documentation
|
| 141 |
+
uv run mkdocs serve # Serve documentation locally (http://127.0.0.1:8000)
|
| 142 |
```
|
| 143 |
|
| 144 |
+
### Test Markers
|
| 145 |
+
|
| 146 |
+
The project uses pytest markers to categorize tests. See [Testing Guidelines](docs/contributing/testing.md) for details:
|
| 147 |
+
|
| 148 |
+
- `unit`: Unit tests (mocked, fast)
|
| 149 |
+
- `integration`: Integration tests (real APIs)
|
| 150 |
+
- `slow`: Slow tests
|
| 151 |
+
- `openai`: Tests requiring OpenAI API key
|
| 152 |
+
- `huggingface`: Tests requiring HuggingFace API key
|
| 153 |
+
- `embedding_provider`: Tests requiring API-based embedding providers
|
| 154 |
+
- `local_embeddings`: Tests using local embeddings
|
| 155 |
+
|
| 156 |
+
**Note**: The `-p no:logfire` flag disables the logfire plugin to avoid conflicts during testing.
|
| 157 |
+
|
| 158 |
## Code Style & Conventions
|
| 159 |
|
| 160 |
### Type Safety
|
|
|
|
| 200 |
|
| 201 |
### Pre-commit
|
| 202 |
|
| 203 |
+
- Pre-commit hooks run automatically on commit
|
| 204 |
- Must pass: lint + typecheck + test-cov
|
| 205 |
+
- Install hooks with: `uv run pre-commit install`
|
| 206 |
+
- Note: `uv sync --all-extras` installs the pre-commit package, but you must run `uv run pre-commit install` separately to set up the git hooks
|
| 207 |
|
| 208 |
## Error Handling & Logging
|
| 209 |
|
|
|
|
| 273 |
1. Write failing test in `tests/unit/`
|
| 274 |
2. Implement in `src/`
|
| 275 |
3. Ensure test passes
|
| 276 |
+
4. Run checks: `uv run ruff check src tests && uv run mypy src && uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire`
|
| 277 |
|
| 278 |
### Test Examples
|
| 279 |
|
|
|
|
| 294 |
|
| 295 |
### Test Coverage
|
| 296 |
|
| 297 |
+
- Run `uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire` for coverage report
|
| 298 |
+
- Run `uv run pytest --cov=src --cov-report=html -p no:logfire` for HTML coverage report (opens `htmlcov/index.html`)
|
| 299 |
- Aim for >80% coverage on critical paths
|
| 300 |
- Exclude: `__init__.py`, `TYPE_CHECKING` blocks
|
| 301 |
|
|
|
|
| 468 |
|
| 469 |
## Pull Request Process
|
| 470 |
|
| 471 |
+
1. Ensure all checks pass: `uv run ruff check src tests && uv run mypy src && uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire`
|
| 472 |
2. Update documentation if needed
|
| 473 |
3. Add tests for new features
|
| 474 |
4. Update CHANGELOG if applicable
|
|
|
|
| 476 |
6. Address review feedback
|
| 477 |
7. Wait for approval before merging
|
| 478 |
|
| 479 |
+
## Project Structure
|
| 480 |
+
|
| 481 |
+
- `src/`: Main source code
|
| 482 |
+
- `tests/`: Test files (`unit/` and `integration/`)
|
| 483 |
+
- `docs/`: Documentation source files (MkDocs)
|
| 484 |
+
- `examples/`: Example usage scripts
|
| 485 |
+
- `pyproject.toml`: Project configuration and dependencies
|
| 486 |
+
- `.pre-commit-config.yaml`: Pre-commit hook configuration
|
| 487 |
+
|
| 488 |
## Questions?
|
| 489 |
|
| 490 |
+
- Open an issue on [GitHub](https://github.com/DeepCritical/GradioDemo)
|
| 491 |
+
- Check existing [documentation](https://deepcritical.github.io/GradioDemo/)
|
| 492 |
- Review code examples in the codebase
|
| 493 |
|
| 494 |
+
Thank you for contributing to The DETERMINATOR!
|
|
|
ERROR_FIXES_SUMMARY.md
DELETED
|
@@ -1,156 +0,0 @@
|
|
| 1 |
-
# Error Fixes Summary
|
| 2 |
-
|
| 3 |
-
## Issues Identified and Fixed
|
| 4 |
-
|
| 5 |
-
### 1. ✅ `'Settings' object has no attribute 'ocr_api_url'`
|
| 6 |
-
|
| 7 |
-
**Error Location:** `src/services/image_ocr.py:33`
|
| 8 |
-
|
| 9 |
-
**Root Cause:**
|
| 10 |
-
The code was trying to access `settings.ocr_api_url` which doesn't exist in older versions of the config. This happens when running a previous version of the app where `ocr_api_url` wasn't added to the Settings class yet.
|
| 11 |
-
|
| 12 |
-
**Fix Applied:**
|
| 13 |
-
- Added defensive coding using `getattr()` with a fallback default URL
|
| 14 |
-
- Default URL: `"https://prithivmlmods-multimodal-ocr3.hf.space"`
|
| 15 |
-
|
| 16 |
-
**Code Change:**
|
| 17 |
-
```python
|
| 18 |
-
# Before:
|
| 19 |
-
self.api_url = api_url or settings.ocr_api_url
|
| 20 |
-
|
| 21 |
-
# After:
|
| 22 |
-
default_url = getattr(settings, "ocr_api_url", None) or "https://prithivmlmods-multimodal-ocr3.hf.space"
|
| 23 |
-
self.api_url = api_url or default_url
|
| 24 |
-
```
|
| 25 |
-
|
| 26 |
-
**File:** `src/services/image_ocr.py`
|
| 27 |
-
|
| 28 |
-
---
|
| 29 |
-
|
| 30 |
-
### 2. ✅ `Expected code to be unreachable, but got: ('research_complete', False)`
|
| 31 |
-
|
| 32 |
-
**Error Location:** `src/orchestrator/graph_orchestrator.py` (decision node execution)
|
| 33 |
-
|
| 34 |
-
**Root Cause:**
|
| 35 |
-
When Pydantic AI encounters a validation error or returns an unexpected format, it may return a tuple like `('research_complete', False)` instead of the expected `KnowledgeGapOutput` object. The decision function was trying to access `result.research_complete` on a tuple, causing the error.
|
| 36 |
-
|
| 37 |
-
**Fix Applied:**
|
| 38 |
-
1. **Enhanced decision function** in `graph_builder.py` to handle tuple formats
|
| 39 |
-
2. **Improved tuple handling** in `graph_orchestrator.py` decision node execution
|
| 40 |
-
3. **Better reconstruction** of `KnowledgeGapOutput` from validation error tuples
|
| 41 |
-
|
| 42 |
-
**Code Changes:**
|
| 43 |
-
|
| 44 |
-
**File: `src/agent_factory/graph_builder.py`**
|
| 45 |
-
- Replaced lambda with named function `_decision_function()` that handles tuples
|
| 46 |
-
- Added logic to extract `research_complete` from various tuple formats
|
| 47 |
-
- Handles: `('research_complete', False)`, dicts in tuples, boolean values in tuples
|
| 48 |
-
|
| 49 |
-
**File: `src/orchestrator/graph_orchestrator.py`**
|
| 50 |
-
- Enhanced tuple detection and reconstruction in `_execute_decision_node()`
|
| 51 |
-
- Added specific handling for `('research_complete', False)` format
|
| 52 |
-
- Improved fallback logic for unexpected tuple formats
|
| 53 |
-
- Better error messages and logging
|
| 54 |
-
|
| 55 |
-
**File: `src/orchestrator/graph_orchestrator.py` (agent node execution)**
|
| 56 |
-
- Improved handling of tuple outputs in `_execute_agent_node()`
|
| 57 |
-
- Better reconstruction of `KnowledgeGapOutput` from validation errors
|
| 58 |
-
- More graceful fallback for non-knowledge_gap nodes
|
| 59 |
-
|
| 60 |
-
---
|
| 61 |
-
|
| 62 |
-
### 3. ⚠️ `Local state is not initialized - app is not locally available` (Modal TTS)
|
| 63 |
-
|
| 64 |
-
**Error Location:** Modal TTS service
|
| 65 |
-
|
| 66 |
-
**Root Cause:**
|
| 67 |
-
This is expected behavior when Modal credentials are not configured or the app is not running in a Modal environment. It's not a critical error - TTS will simply be unavailable.
|
| 68 |
-
|
| 69 |
-
**Status:**
|
| 70 |
-
- This is **not an error** - it's expected when Modal isn't configured
|
| 71 |
-
- The app gracefully degrades and continues without TTS
|
| 72 |
-
- Users can still use the app, just without audio output
|
| 73 |
-
|
| 74 |
-
**No Fix Needed:** This is working as designed with graceful degradation.
|
| 75 |
-
|
| 76 |
-
---
|
| 77 |
-
|
| 78 |
-
### 4. ⚠️ `Invalid file descriptor: -1` (Asyncio cleanup)
|
| 79 |
-
|
| 80 |
-
**Error Location:** Python asyncio event loop cleanup
|
| 81 |
-
|
| 82 |
-
**Root Cause:**
|
| 83 |
-
This is a Python asyncio cleanup warning that occurs during shutdown. It's not critical and doesn't affect functionality.
|
| 84 |
-
|
| 85 |
-
**Status:**
|
| 86 |
-
- This is a **warning**, not an error
|
| 87 |
-
- Occurs during application shutdown
|
| 88 |
-
- Doesn't affect runtime functionality
|
| 89 |
-
- Common in Python 3.11+ with certain asyncio patterns
|
| 90 |
-
|
| 91 |
-
**No Fix Needed:** This is a known Python asyncio quirk and doesn't impact functionality.
|
| 92 |
-
|
| 93 |
-
---
|
| 94 |
-
|
| 95 |
-
### 5. ⚠️ MCP Server Warning: `gr.State input will not be updated between tool calls`
|
| 96 |
-
|
| 97 |
-
**Error Location:** Gradio MCP server setup
|
| 98 |
-
|
| 99 |
-
**Root Cause:**
|
| 100 |
-
Some MCP tools use `gr.State` inputs, which Gradio warns won't update between tool calls. This is a limitation of how MCP tools interact with Gradio state.
|
| 101 |
-
|
| 102 |
-
**Status:**
|
| 103 |
-
- This is a **warning**, not an error
|
| 104 |
-
- MCP tools will still work, but state won't persist between calls
|
| 105 |
-
- This is a known Gradio MCP limitation
|
| 106 |
-
|
| 107 |
-
**No Fix Needed:** This is a Gradio limitation, not a bug in our code.
|
| 108 |
-
|
| 109 |
-
---
|
| 110 |
-
|
| 111 |
-
## Summary of Fixes
|
| 112 |
-
|
| 113 |
-
### Critical Fixes (Applied):
|
| 114 |
-
1. ✅ **OCR API URL Attribute Error** - Fixed with defensive coding
|
| 115 |
-
2. ✅ **Graph Orchestrator Tuple Handling** - Fixed with enhanced tuple detection and reconstruction
|
| 116 |
-
|
| 117 |
-
### Non-Critical (Expected Behavior):
|
| 118 |
-
3. ⚠️ **Modal TTS Error** - Expected when Modal not configured (graceful degradation)
|
| 119 |
-
4. ⚠️ **Asyncio Cleanup Warning** - Python asyncio quirk (non-critical)
|
| 120 |
-
5. ⚠️ **MCP State Warning** - Gradio limitation (non-critical)
|
| 121 |
-
|
| 122 |
-
## Testing Recommendations
|
| 123 |
-
|
| 124 |
-
1. **Test OCR functionality:**
|
| 125 |
-
- Upload an image with text
|
| 126 |
-
- Verify OCR processing works
|
| 127 |
-
- Check logs for any remaining errors
|
| 128 |
-
|
| 129 |
-
2. **Test graph execution:**
|
| 130 |
-
- Run a research query
|
| 131 |
-
- Verify knowledge gap evaluation works
|
| 132 |
-
- Check that decision nodes route correctly
|
| 133 |
-
- Monitor logs for tuple handling warnings
|
| 134 |
-
|
| 135 |
-
3. **Test with/without Modal:**
|
| 136 |
-
- Verify app works without Modal credentials
|
| 137 |
-
- Test TTS if Modal is configured
|
| 138 |
-
- Verify graceful degradation
|
| 139 |
-
|
| 140 |
-
## Files Modified
|
| 141 |
-
|
| 142 |
-
1. `src/services/image_ocr.py` - Added defensive `ocr_api_url` access
|
| 143 |
-
2. `src/orchestrator/graph_orchestrator.py` - Enhanced tuple handling in decision and agent nodes
|
| 144 |
-
3. `src/agent_factory/graph_builder.py` - Improved decision function to handle tuples
|
| 145 |
-
|
| 146 |
-
## Next Steps
|
| 147 |
-
|
| 148 |
-
1. Test the fixes with the reported error scenarios
|
| 149 |
-
2. Monitor logs for any remaining issues
|
| 150 |
-
3. Consider adding unit tests for tuple handling edge cases
|
| 151 |
-
4. Document the tuple format handling for future reference
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FILE_OUTPUT_IMPLEMENTATION_PLAN.md
DELETED
|
@@ -1,241 +0,0 @@
|
|
| 1 |
-
# File Output Implementation Plan
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
This plan implements file writing and return functionality for report-writing agents, enabling reports to be saved as files and returned through the Gradio ChatInterface.
|
| 6 |
-
|
| 7 |
-
## Current State Analysis
|
| 8 |
-
|
| 9 |
-
✅ **Report Generation**: All agents generate markdown strings
|
| 10 |
-
✅ **File Output Integration**: `event_to_chat_message()` supports file paths
|
| 11 |
-
✅ **Graph Orchestrator**: Can handle file paths in results
|
| 12 |
-
❌ **File Writing**: No agents write files to disk
|
| 13 |
-
❌ **File Service**: No utility service for saving reports
|
| 14 |
-
|
| 15 |
-
---
|
| 16 |
-
|
| 17 |
-
## Implementation Plan
|
| 18 |
-
|
| 19 |
-
### PROJECT 1: File Writing Service
|
| 20 |
-
**Goal**: Create a reusable service for saving reports to files
|
| 21 |
-
|
| 22 |
-
#### Activity 1.1: Create Report File Service
|
| 23 |
-
**File**: `src/services/report_file_service.py` (NEW)
|
| 24 |
-
|
| 25 |
-
**Tasks**:
|
| 26 |
-
1. Create `ReportFileService` class
|
| 27 |
-
2. Implement `save_report()` method
|
| 28 |
-
- Accepts: report content (str), filename (optional), output_dir (optional)
|
| 29 |
-
- Returns: file path (str)
|
| 30 |
-
- Uses temp directory by default
|
| 31 |
-
- Supports custom output directory
|
| 32 |
-
- Handles file naming with timestamps
|
| 33 |
-
3. Implement `save_report_multiple_formats()` method
|
| 34 |
-
- Save as .md (always)
|
| 35 |
-
- Optionally save as .html, .pdf (future)
|
| 36 |
-
4. Add configuration support
|
| 37 |
-
- Read from settings
|
| 38 |
-
- Enable/disable file saving
|
| 39 |
-
- Configurable output directory
|
| 40 |
-
5. Add error handling and logging
|
| 41 |
-
6. Add file cleanup utilities (optional)
|
| 42 |
-
|
| 43 |
-
**Line-level subtasks**:
|
| 44 |
-
- Line 1-20: Imports and class definition
|
| 45 |
-
- Line 21-40: `__init__()` method with settings
|
| 46 |
-
- Line 41-80: `save_report()` method
|
| 47 |
-
- Line 41-50: Input validation
|
| 48 |
-
- Line 51-60: Directory creation
|
| 49 |
-
- Line 61-70: File writing
|
| 50 |
-
- Line 71-80: Error handling
|
| 51 |
-
- Line 81-100: `save_report_multiple_formats()` method
|
| 52 |
-
- Line 101-120: Helper methods (filename generation, cleanup)
|
| 53 |
-
|
| 54 |
-
---
|
| 55 |
-
|
| 56 |
-
### PROJECT 2: Configuration Updates
|
| 57 |
-
**Goal**: Add settings for file output functionality
|
| 58 |
-
|
| 59 |
-
#### Activity 2.1: Update Settings Model
|
| 60 |
-
**File**: `src/utils/config.py`
|
| 61 |
-
|
| 62 |
-
**Tasks**:
|
| 63 |
-
1. Add `save_reports_to_file: bool` field (default: True)
|
| 64 |
-
2. Add `report_output_directory: str | None` field (default: None, uses temp)
|
| 65 |
-
3. Add `report_file_format: Literal["md", "md_html", "md_pdf"]` field (default: "md")
|
| 66 |
-
4. Add `report_filename_template: str` field (default: "report_{timestamp}_{query_hash}.md")
|
| 67 |
-
|
| 68 |
-
**Line-level subtasks**:
|
| 69 |
-
- Line 166-170: Add `save_reports_to_file` field after TTS config
|
| 70 |
-
- Line 171-175: Add `report_output_directory` field
|
| 71 |
-
- Line 176-180: Add `report_file_format` field
|
| 72 |
-
- Line 181-185: Add `report_filename_template` field
|
| 73 |
-
|
| 74 |
-
---
|
| 75 |
-
|
| 76 |
-
### PROJECT 3: Graph Orchestrator Integration
|
| 77 |
-
**Goal**: Integrate file writing into graph execution
|
| 78 |
-
|
| 79 |
-
#### Activity 3.1: Update Graph Orchestrator
|
| 80 |
-
**File**: `src/orchestrator/graph_orchestrator.py`
|
| 81 |
-
|
| 82 |
-
**Tasks**:
|
| 83 |
-
1. Import `ReportFileService` at top
|
| 84 |
-
2. Initialize service in `__init__()` (optional, can be lazy)
|
| 85 |
-
3. Modify `_execute_agent_node()` for synthesizer node
|
| 86 |
-
- After `long_writer_agent.write_report()`, save to file
|
| 87 |
-
- Return dict with `{"message": report, "file": file_path}`
|
| 88 |
-
4. Update final event generation to handle file paths
|
| 89 |
-
- Already implemented, verify it works correctly
|
| 90 |
-
|
| 91 |
-
**Line-level subtasks**:
|
| 92 |
-
- Line 1-35: Add import for `ReportFileService`
|
| 93 |
-
- Line 119-148: Update `__init__()` to accept optional file service
|
| 94 |
-
- Line 589-650: Modify `_execute_agent_node()` synthesizer handling
|
| 95 |
-
- Line 642-645: After `write_report()`, add file saving
|
| 96 |
-
- Line 646-650: Return dict with file path
|
| 97 |
-
- Line 534-564: Verify final event generation handles file paths (already done)
|
| 98 |
-
|
| 99 |
-
---
|
| 100 |
-
|
| 101 |
-
### PROJECT 4: Research Flow Integration
|
| 102 |
-
**Goal**: Integrate file writing into research flows
|
| 103 |
-
|
| 104 |
-
#### Activity 4.1: Update IterativeResearchFlow
|
| 105 |
-
**File**: `src/orchestrator/research_flow.py`
|
| 106 |
-
|
| 107 |
-
**Tasks**:
|
| 108 |
-
1. Import `ReportFileService` at top
|
| 109 |
-
2. Add optional file service to `__init__()`
|
| 110 |
-
3. Modify `_create_final_report()` method
|
| 111 |
-
- After `writer_agent.write_report()`, save to file if enabled
|
| 112 |
-
- Return string (backward compatible) OR dict with file path
|
| 113 |
-
|
| 114 |
-
**Line-level subtasks**:
|
| 115 |
-
- Line 1-50: Add import for `ReportFileService`
|
| 116 |
-
- Line 48-120: Update `__init__()` to accept optional file service
|
| 117 |
-
- Line 622-667: Modify `_create_final_report()` method
|
| 118 |
-
- Line 647-652: After `write_report()`, add file saving
|
| 119 |
-
- Line 653-667: Return report string (keep backward compatible for now)
|
| 120 |
-
|
| 121 |
-
#### Activity 4.2: Update DeepResearchFlow
|
| 122 |
-
**File**: `src/orchestrator/research_flow.py`
|
| 123 |
-
|
| 124 |
-
**Tasks**:
|
| 125 |
-
1. Add optional file service to `__init__()` (if not already)
|
| 126 |
-
2. Modify `_create_final_report()` method
|
| 127 |
-
- After `long_writer_agent.write_report()` or `proofreader_agent.proofread()`, save to file
|
| 128 |
-
- Return string (backward compatible) OR dict with file path
|
| 129 |
-
|
| 130 |
-
**Line-level subtasks**:
|
| 131 |
-
- Line 670-750: Update `DeepResearchFlow.__init__()` to accept optional file service
|
| 132 |
-
- Line 954-1005: Modify `_create_final_report()` method
|
| 133 |
-
- Line 979-983: After `write_report()`, add file saving
|
| 134 |
-
- Line 984-989: After `proofread()`, add file saving
|
| 135 |
-
- Line 990-1005: Return report string (keep backward compatible)
|
| 136 |
-
|
| 137 |
-
---
|
| 138 |
-
|
| 139 |
-
### PROJECT 5: Agent Factory Integration
|
| 140 |
-
**Goal**: Make file service available to agents if needed
|
| 141 |
-
|
| 142 |
-
#### Activity 5.1: Update Agent Factory (Optional)
|
| 143 |
-
**File**: `src/agent_factory/agents.py`
|
| 144 |
-
|
| 145 |
-
**Tasks**:
|
| 146 |
-
1. Add optional file service parameter to agent creation functions (if needed)
|
| 147 |
-
2. Pass file service to agents that need it (currently not needed, agents return strings)
|
| 148 |
-
|
| 149 |
-
**Line-level subtasks**:
|
| 150 |
-
- Not required - agents return strings, file writing happens at orchestrator level
|
| 151 |
-
|
| 152 |
-
---
|
| 153 |
-
|
| 154 |
-
### PROJECT 6: Testing & Validation
|
| 155 |
-
**Goal**: Ensure file output works end-to-end
|
| 156 |
-
|
| 157 |
-
#### Activity 6.1: Unit Tests
|
| 158 |
-
**File**: `tests/unit/services/test_report_file_service.py` (NEW)
|
| 159 |
-
|
| 160 |
-
**Tasks**:
|
| 161 |
-
1. Test `save_report()` with default settings
|
| 162 |
-
2. Test `save_report()` with custom directory
|
| 163 |
-
3. Test `save_report()` with custom filename
|
| 164 |
-
4. Test error handling (permission errors, disk full, etc.)
|
| 165 |
-
5. Test file cleanup
|
| 166 |
-
|
| 167 |
-
**Line-level subtasks**:
|
| 168 |
-
- Line 1-30: Test fixtures and setup
|
| 169 |
-
- Line 31-60: Test basic save functionality
|
| 170 |
-
- Line 61-90: Test custom directory
|
| 171 |
-
- Line 91-120: Test error handling
|
| 172 |
-
|
| 173 |
-
#### Activity 6.2: Integration Tests
|
| 174 |
-
**File**: `tests/integration/test_file_output_integration.py` (NEW)
|
| 175 |
-
|
| 176 |
-
**Tasks**:
|
| 177 |
-
1. Test graph orchestrator with file output
|
| 178 |
-
2. Test research flows with file output
|
| 179 |
-
3. Test Gradio ChatInterface receives file paths
|
| 180 |
-
4. Test file download in Gradio UI
|
| 181 |
-
|
| 182 |
-
**Line-level subtasks**:
|
| 183 |
-
- Line 1-40: Test setup with mock orchestrator
|
| 184 |
-
- Line 41-80: Test file generation in graph execution
|
| 185 |
-
- Line 81-120: Test file paths in AgentEvent
|
| 186 |
-
- Line 121-160: Test Gradio message conversion
|
| 187 |
-
|
| 188 |
-
---
|
| 189 |
-
|
| 190 |
-
## Implementation Order
|
| 191 |
-
|
| 192 |
-
1. **PROJECT 2** (Configuration) - Foundation
|
| 193 |
-
2. **PROJECT 1** (File Service) - Core functionality
|
| 194 |
-
3. **PROJECT 3** (Graph Orchestrator) - Primary integration point
|
| 195 |
-
4. **PROJECT 4** (Research Flows) - Secondary integration points
|
| 196 |
-
5. **PROJECT 6** (Testing) - Validation
|
| 197 |
-
6. **PROJECT 5** (Agent Factory) - Not needed, skip
|
| 198 |
-
|
| 199 |
-
---
|
| 200 |
-
|
| 201 |
-
## File Changes Summary
|
| 202 |
-
|
| 203 |
-
### New Files
|
| 204 |
-
- `src/services/report_file_service.py` - File writing service
|
| 205 |
-
- `tests/unit/services/test_report_file_service.py` - Unit tests
|
| 206 |
-
- `tests/integration/test_file_output_integration.py` - Integration tests
|
| 207 |
-
|
| 208 |
-
### Modified Files
|
| 209 |
-
- `src/utils/config.py` - Add file output settings
|
| 210 |
-
- `src/orchestrator/graph_orchestrator.py` - Add file saving after report generation
|
| 211 |
-
- `src/orchestrator/research_flow.py` - Add file saving in both flows
|
| 212 |
-
|
| 213 |
-
---
|
| 214 |
-
|
| 215 |
-
## Gradio Integration Notes
|
| 216 |
-
|
| 217 |
-
According to Gradio ChatInterface documentation:
|
| 218 |
-
- File paths in chat message content are automatically converted to download links
|
| 219 |
-
- Markdown links like `[Download: filename](file_path)` work
|
| 220 |
-
- Files must be accessible from the Gradio server
|
| 221 |
-
- Temp files are fine as long as they exist during the session
|
| 222 |
-
|
| 223 |
-
Current implementation in `event_to_chat_message()` already handles this correctly.
|
| 224 |
-
|
| 225 |
-
---
|
| 226 |
-
|
| 227 |
-
## Success Criteria
|
| 228 |
-
|
| 229 |
-
✅ Reports are saved to files when generated
|
| 230 |
-
✅ File paths are included in AgentEvent data
|
| 231 |
-
✅ File paths appear as download links in Gradio ChatInterface
|
| 232 |
-
✅ File saving is configurable (can be disabled)
|
| 233 |
-
✅ Backward compatible (existing code still works)
|
| 234 |
-
✅ Error handling prevents crashes if file writing fails
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FILE_OUTPUT_VERIFICATION.md
DELETED
|
@@ -1,224 +0,0 @@
|
|
| 1 |
-
# File Output Implementation Verification
|
| 2 |
-
|
| 3 |
-
## Status: ✅ ALL CHANGES RETAINED
|
| 4 |
-
|
| 5 |
-
All file output functionality has been successfully implemented and retained in the codebase.
|
| 6 |
-
|
| 7 |
-
---
|
| 8 |
-
|
| 9 |
-
## Verification Checklist
|
| 10 |
-
|
| 11 |
-
### ✅ PROJECT 1: File Writing Service
|
| 12 |
-
- **File**: `src/services/report_file_service.py`
|
| 13 |
-
- **Status**: ✅ EXISTS
|
| 14 |
-
- **Key Components**:
|
| 15 |
-
- `ReportFileService` class
|
| 16 |
-
- `save_report()` method
|
| 17 |
-
- `save_report_multiple_formats()` method
|
| 18 |
-
- `_generate_filename()` helper
|
| 19 |
-
- `_sanitize_filename()` helper
|
| 20 |
-
- `cleanup_old_files()` method
|
| 21 |
-
- `get_report_file_service()` singleton function
|
| 22 |
-
|
| 23 |
-
### ✅ PROJECT 2: Configuration Updates
|
| 24 |
-
- **File**: `src/utils/config.py`
|
| 25 |
-
- **Status**: ✅ ALL SETTINGS PRESENT
|
| 26 |
-
- **Settings Added** (lines 181-195):
|
| 27 |
-
- ✅ `save_reports_to_file: bool = True`
|
| 28 |
-
- ✅ `report_output_directory: str | None = None`
|
| 29 |
-
- ✅ `report_file_format: Literal["md", "md_html", "md_pdf"] = "md"`
|
| 30 |
-
- ✅ `report_filename_template: str = "report_{timestamp}_{query_hash}.md"`
|
| 31 |
-
|
| 32 |
-
### ✅ PROJECT 3: Graph Orchestrator Integration
|
| 33 |
-
- **File**: `src/orchestrator/graph_orchestrator.py`
|
| 34 |
-
- **Status**: ✅ FULLY INTEGRATED
|
| 35 |
-
|
| 36 |
-
#### Imports (Line 35)
|
| 37 |
-
```python
|
| 38 |
-
from src.services.report_file_service import ReportFileService, get_report_file_service
|
| 39 |
-
```
|
| 40 |
-
✅ Present
|
| 41 |
-
|
| 42 |
-
#### File Service Initialization (Line 152)
|
| 43 |
-
```python
|
| 44 |
-
self._file_service: ReportFileService | None = None
|
| 45 |
-
```
|
| 46 |
-
✅ Present
|
| 47 |
-
|
| 48 |
-
#### Helper Method (Lines 162-175)
|
| 49 |
-
```python
|
| 50 |
-
def _get_file_service(self) -> ReportFileService | None:
|
| 51 |
-
"""Get file service instance (lazy initialization)."""
|
| 52 |
-
...
|
| 53 |
-
```
|
| 54 |
-
✅ Present
|
| 55 |
-
|
| 56 |
-
#### Synthesizer Node File Saving (Lines 673-694)
|
| 57 |
-
- ✅ Saves report after `long_writer_agent.write_report()`
|
| 58 |
-
- ✅ Returns dict with `{"message": report, "file": file_path}` if file saved
|
| 59 |
-
- ✅ Returns string if file saving fails (backward compatible)
|
| 60 |
-
- ✅ Error handling with logging
|
| 61 |
-
|
| 62 |
-
#### Writer Node File Saving (Lines 729-748)
|
| 63 |
-
- ✅ Saves report after `writer_agent.write_report()`
|
| 64 |
-
- ✅ Returns dict with `{"message": report, "file": file_path}` if file saved
|
| 65 |
-
- ✅ Returns string if file saving fails (backward compatible)
|
| 66 |
-
- ✅ Error handling with logging
|
| 67 |
-
|
| 68 |
-
#### Final Event Handling (Lines 558-585)
|
| 69 |
-
- ✅ Extracts file path from final result dict
|
| 70 |
-
- ✅ Adds file path to `event_data["file"]` or `event_data["files"]`
|
| 71 |
-
- ✅ Handles both single file and multiple files
|
| 72 |
-
- ✅ Sets appropriate message
|
| 73 |
-
|
| 74 |
-
### ✅ PROJECT 4: Research Flow Integration
|
| 75 |
-
- **File**: `src/orchestrator/research_flow.py`
|
| 76 |
-
- **Status**: ✅ FULLY INTEGRATED
|
| 77 |
-
|
| 78 |
-
#### Imports (Line 28)
|
| 79 |
-
```python
|
| 80 |
-
from src.services.report_file_service import ReportFileService, get_report_file_service
|
| 81 |
-
```
|
| 82 |
-
✅ Present
|
| 83 |
-
|
| 84 |
-
#### IterativeResearchFlow
|
| 85 |
-
- **File Service Initialization** (Line 117): ✅ Present
|
| 86 |
-
- **Helper Method** (Lines 119-132): ✅ Present
|
| 87 |
-
- **File Saving in `_create_final_report()`** (Lines 683-692): ✅ Present
|
| 88 |
-
- Saves after `writer_agent.write_report()`
|
| 89 |
-
- Logs file path
|
| 90 |
-
- Error handling with logging
|
| 91 |
-
|
| 92 |
-
#### DeepResearchFlow
|
| 93 |
-
- **File Service Initialization** (Line 761): ✅ Present
|
| 94 |
-
- **Helper Method** (Lines 763-776): ✅ Present
|
| 95 |
-
- **File Saving in `_create_final_report()`** (Lines 1055-1064): ✅ Present
|
| 96 |
-
- Saves after `long_writer_agent.write_report()` or `proofreader_agent.proofread()`
|
| 97 |
-
- Logs file path
|
| 98 |
-
- Error handling with logging
|
| 99 |
-
|
| 100 |
-
### ✅ PROJECT 5: Gradio Integration
|
| 101 |
-
- **File**: `src/app.py`
|
| 102 |
-
- **Status**: ✅ ALREADY IMPLEMENTED (from previous work)
|
| 103 |
-
- **Function**: `event_to_chat_message()` (Lines 209-350)
|
| 104 |
-
- **Features**:
|
| 105 |
-
- ✅ Detects file paths in `event.data["file"]` or `event.data["files"]`
|
| 106 |
-
- ✅ Formats files as markdown download links
|
| 107 |
-
- ✅ Handles both single and multiple files
|
| 108 |
-
- ✅ Validates file paths with `_is_file_path()` helper
|
| 109 |
-
|
| 110 |
-
---
|
| 111 |
-
|
| 112 |
-
## Implementation Summary
|
| 113 |
-
|
| 114 |
-
### File Saving Locations
|
| 115 |
-
|
| 116 |
-
1. **Graph Orchestrator - Synthesizer Node** (Deep Research)
|
| 117 |
-
- Location: `src/orchestrator/graph_orchestrator.py:673-694`
|
| 118 |
-
- Trigger: After `long_writer_agent.write_report()`
|
| 119 |
-
- Returns: Dict with file path or string (backward compatible)
|
| 120 |
-
|
| 121 |
-
2. **Graph Orchestrator - Writer Node** (Iterative Research)
|
| 122 |
-
- Location: `src/orchestrator/graph_orchestrator.py:729-748`
|
| 123 |
-
- Trigger: After `writer_agent.write_report()`
|
| 124 |
-
- Returns: Dict with file path or string (backward compatible)
|
| 125 |
-
|
| 126 |
-
3. **IterativeResearchFlow**
|
| 127 |
-
- Location: `src/orchestrator/research_flow.py:683-692`
|
| 128 |
-
- Trigger: After `writer_agent.write_report()` in `_create_final_report()`
|
| 129 |
-
- Returns: String (file path logged, not returned)
|
| 130 |
-
|
| 131 |
-
4. **DeepResearchFlow**
|
| 132 |
-
- Location: `src/orchestrator/research_flow.py:1055-1064`
|
| 133 |
-
- Trigger: After `long_writer_agent.write_report()` or `proofreader_agent.proofread()`
|
| 134 |
-
- Returns: String (file path logged, not returned)
|
| 135 |
-
|
| 136 |
-
### File Path Flow
|
| 137 |
-
|
| 138 |
-
```
|
| 139 |
-
Report Generation
|
| 140 |
-
↓
|
| 141 |
-
ReportFileService.save_report()
|
| 142 |
-
↓
|
| 143 |
-
File saved to disk (temp directory or configured directory)
|
| 144 |
-
↓
|
| 145 |
-
File path returned to orchestrator
|
| 146 |
-
↓
|
| 147 |
-
File path included in result dict: {"message": report, "file": file_path}
|
| 148 |
-
↓
|
| 149 |
-
Result dict stored in GraphExecutionContext
|
| 150 |
-
↓
|
| 151 |
-
Final event extraction (lines 558-585)
|
| 152 |
-
↓
|
| 153 |
-
File path added to AgentEvent.data["file"]
|
| 154 |
-
↓
|
| 155 |
-
event_to_chat_message() (src/app.py)
|
| 156 |
-
↓
|
| 157 |
-
File path formatted as markdown download link
|
| 158 |
-
↓
|
| 159 |
-
Gradio ChatInterface displays download link
|
| 160 |
-
```
|
| 161 |
-
|
| 162 |
-
---
|
| 163 |
-
|
| 164 |
-
## Testing Recommendations
|
| 165 |
-
|
| 166 |
-
### Unit Tests
|
| 167 |
-
- [ ] Test `ReportFileService.save_report()` with various inputs
|
| 168 |
-
- [ ] Test filename generation with templates
|
| 169 |
-
- [ ] Test file sanitization
|
| 170 |
-
- [ ] Test error handling (permission errors, disk full, etc.)
|
| 171 |
-
|
| 172 |
-
### Integration Tests
|
| 173 |
-
- [ ] Test graph orchestrator file saving for synthesizer node
|
| 174 |
-
- [ ] Test graph orchestrator file saving for writer node
|
| 175 |
-
- [ ] Test file path inclusion in AgentEvent
|
| 176 |
-
- [ ] Test Gradio message conversion with file paths
|
| 177 |
-
- [ ] Test file download in Gradio UI
|
| 178 |
-
|
| 179 |
-
### Manual Testing
|
| 180 |
-
- [ ] Run iterative research flow and verify file is created
|
| 181 |
-
- [ ] Run deep research flow and verify file is created
|
| 182 |
-
- [ ] Verify file appears as download link in Gradio ChatInterface
|
| 183 |
-
- [ ] Test with file saving disabled (`save_reports_to_file=False`)
|
| 184 |
-
- [ ] Test with custom output directory
|
| 185 |
-
|
| 186 |
-
---
|
| 187 |
-
|
| 188 |
-
## Configuration Options
|
| 189 |
-
|
| 190 |
-
All settings are in `src/utils/config.py`:
|
| 191 |
-
|
| 192 |
-
```python
|
| 193 |
-
# Enable/disable file saving
|
| 194 |
-
save_reports_to_file: bool = True
|
| 195 |
-
|
| 196 |
-
# Custom output directory (None = use temp directory)
|
| 197 |
-
report_output_directory: str | None = None
|
| 198 |
-
|
| 199 |
-
# File format (currently only "md" is fully implemented)
|
| 200 |
-
report_file_format: Literal["md", "md_html", "md_pdf"] = "md"
|
| 201 |
-
|
| 202 |
-
# Filename template with placeholders
|
| 203 |
-
report_filename_template: str = "report_{timestamp}_{query_hash}.md"
|
| 204 |
-
```
|
| 205 |
-
|
| 206 |
-
---
|
| 207 |
-
|
| 208 |
-
## Conclusion
|
| 209 |
-
|
| 210 |
-
✅ **All file output functionality has been successfully implemented and retained.**
|
| 211 |
-
|
| 212 |
-
The implementation is:
|
| 213 |
-
- ✅ Complete (all planned features implemented)
|
| 214 |
-
- ✅ Backward compatible (existing code continues to work)
|
| 215 |
-
- ✅ Error resilient (file saving failures don't crash workflows)
|
| 216 |
-
- ✅ Configurable (can be enabled/disabled via settings)
|
| 217 |
-
- ✅ Integrated with Gradio (file paths appear as download links)
|
| 218 |
-
|
| 219 |
-
No reimplementation needed. All changes are present and correct.
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FIX_SUMMARY.md
DELETED
|
@@ -1,102 +0,0 @@
|
|
| 1 |
-
# Fix Summary: Research Results Not Returned to User
|
| 2 |
-
|
| 3 |
-
## Problem
|
| 4 |
-
The application was returning "Research completed" instead of the actual research report content to users. Reports were being generated and saved to files, but the final result wasn't being properly extracted and returned to the Gradio interface.
|
| 5 |
-
|
| 6 |
-
## Root Causes
|
| 7 |
-
|
| 8 |
-
1. **Incomplete Result Extraction**: The `_execute_graph` method in `graph_orchestrator.py` only checked the last executed node (`current_node_id`) for the final result. If the graph execution broke early due to budget/time limits, or if the last node wasn't the synthesizer/writer exit node, the result wouldn't be found.
|
| 9 |
-
|
| 10 |
-
2. **Incomplete Dict Handling**: When the synthesizer or writer nodes returned a dict with `{"message": final_report, "file": file_path}`, the code only extracted the message if the dict had a "file" key. If the dict had a "message" key but no "file" key, the message wouldn't be extracted.
|
| 11 |
-
|
| 12 |
-
3. **No Fallback Logic**: There was no fallback to check all exit nodes for results if the current node wasn't an exit node.
|
| 13 |
-
|
| 14 |
-
## Solution
|
| 15 |
-
|
| 16 |
-
### Changes Made to `src/orchestrator/graph_orchestrator.py`
|
| 17 |
-
|
| 18 |
-
1. **Enhanced Result Extraction** (lines 555-600):
|
| 19 |
-
- First checks if `current_node_id` is an exit node and gets its result
|
| 20 |
-
- If no result, prioritizes checking "synthesizer" and "writer" exit nodes
|
| 21 |
-
- Falls back to checking all exit nodes if still no result
|
| 22 |
-
- Added comprehensive logging to help debug result extraction
|
| 23 |
-
|
| 24 |
-
2. **Improved Dict Handling** (lines 602-640):
|
| 25 |
-
- Now checks for "message" key first (most important)
|
| 26 |
-
- Extracts message from dict even if "file" key is missing
|
| 27 |
-
- Only uses default messages if "message" key is not present
|
| 28 |
-
- Added logging for result type and extraction process
|
| 29 |
-
|
| 30 |
-
3. **Better Error Handling**:
|
| 31 |
-
- Logs warnings when no result is found, including all available node results
|
| 32 |
-
- Logs unexpected result types for debugging
|
| 33 |
-
|
| 34 |
-
## Key Code Changes
|
| 35 |
-
|
| 36 |
-
### Before:
|
| 37 |
-
```python
|
| 38 |
-
final_result = context.get_node_result(current_node_id) if current_node_id else None
|
| 39 |
-
message: str = "Research completed"
|
| 40 |
-
|
| 41 |
-
if isinstance(final_result, str):
|
| 42 |
-
message = final_result
|
| 43 |
-
elif isinstance(final_result, dict):
|
| 44 |
-
if "file" in final_result:
|
| 45 |
-
# Only extracts message if file exists
|
| 46 |
-
message = final_result.get("message", "Report generated. Download available.")
|
| 47 |
-
```
|
| 48 |
-
|
| 49 |
-
### After:
|
| 50 |
-
```python
|
| 51 |
-
# Check all exit nodes with priority
|
| 52 |
-
final_result = None
|
| 53 |
-
if current_node_id and current_node_id in self._graph.exit_nodes:
|
| 54 |
-
final_result = context.get_node_result(current_node_id)
|
| 55 |
-
|
| 56 |
-
if not final_result:
|
| 57 |
-
# Prioritize synthesizer/writer nodes
|
| 58 |
-
for exit_node_id in ["synthesizer", "writer"]:
|
| 59 |
-
if exit_node_id in self._graph.exit_nodes:
|
| 60 |
-
result = context.get_node_result(exit_node_id)
|
| 61 |
-
if result:
|
| 62 |
-
final_result = result
|
| 63 |
-
break
|
| 64 |
-
|
| 65 |
-
# Extract message from dict first
|
| 66 |
-
if isinstance(final_result, dict):
|
| 67 |
-
if "message" in final_result:
|
| 68 |
-
message = final_result["message"] # Extract message regardless of file
|
| 69 |
-
```
|
| 70 |
-
|
| 71 |
-
## Testing Recommendations
|
| 72 |
-
|
| 73 |
-
1. **Test Deep Research Flow**:
|
| 74 |
-
- Run a query that triggers deep research mode
|
| 75 |
-
- Verify the full report is returned, not just "Research completed"
|
| 76 |
-
- Check that reports are properly displayed in the UI
|
| 77 |
-
|
| 78 |
-
2. **Test Iterative Research Flow**:
|
| 79 |
-
- Run a query that triggers iterative research mode
|
| 80 |
-
- Verify the report is returned correctly
|
| 81 |
-
|
| 82 |
-
3. **Test Budget/Time Limits**:
|
| 83 |
-
- Run queries that exceed budget or time limits
|
| 84 |
-
- Verify that partial results are still returned if available
|
| 85 |
-
|
| 86 |
-
4. **Test File Saving**:
|
| 87 |
-
- Verify reports are saved to files
|
| 88 |
-
- Verify file paths are included in event data when available
|
| 89 |
-
|
| 90 |
-
## Files Modified
|
| 91 |
-
|
| 92 |
-
- `src/orchestrator/graph_orchestrator.py`: Enhanced result extraction and message handling logic
|
| 93 |
-
|
| 94 |
-
## Expected Behavior After Fix
|
| 95 |
-
|
| 96 |
-
- Users will see the full research report content in the chat interface
|
| 97 |
-
- Reports will be properly extracted from synthesizer/writer nodes
|
| 98 |
-
- File paths will be included in event data when reports are saved
|
| 99 |
-
- Better logging will help debug any future issues with result extraction
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MULTIMODAL_SETTINGS_IMPLEMENTATION_PLAN.md
DELETED
|
@@ -1,386 +0,0 @@
|
|
| 1 |
-
# Multimodal Settings & File Rendering - Implementation Plan
|
| 2 |
-
|
| 3 |
-
## Executive Summary
|
| 4 |
-
|
| 5 |
-
This document provides a comprehensive analysis of the current settings implementation, multimodal input handling, and file rendering in `src/app.py`, along with a detailed implementation plan to improve the user experience.
|
| 6 |
-
|
| 7 |
-
## 1. Current Settings Analysis
|
| 8 |
-
|
| 9 |
-
### 1.1 Settings Structure in `src/app.py`
|
| 10 |
-
|
| 11 |
-
**Current Implementation (Lines 741-887):**
|
| 12 |
-
|
| 13 |
-
1. **Sidebar Structure:**
|
| 14 |
-
- Authentication section (lines 745-750)
|
| 15 |
-
- About section (lines 752-764)
|
| 16 |
-
- Settings section (lines 767-850):
|
| 17 |
-
- Research Configuration Accordion (lines 771-796):
|
| 18 |
-
- `mode_radio`: Orchestrator mode selector
|
| 19 |
-
- `graph_mode_radio`: Graph research mode selector
|
| 20 |
-
- `use_graph_checkbox`: Graph execution toggle
|
| 21 |
-
- Audio Output Accordion (lines 798-850):
|
| 22 |
-
- `enable_audio_output_checkbox`: TTS enable/disable
|
| 23 |
-
- `tts_voice_dropdown`: Voice selection
|
| 24 |
-
- `tts_speed_slider`: Speech speed control
|
| 25 |
-
- `tts_gpu_dropdown`: GPU type (non-interactive, visible only if Modal available)
|
| 26 |
-
|
| 27 |
-
2. **Hidden Components (Lines 852-865):**
|
| 28 |
-
- `hf_model_dropdown`: Hidden Textbox for model selection
|
| 29 |
-
- `hf_provider_dropdown`: Hidden Textbox for provider selection
|
| 30 |
-
|
| 31 |
-
3. **Main Area Components (Lines 867-887):**
|
| 32 |
-
- `audio_output`: Audio output component (visible based on `settings.enable_audio_output`)
|
| 33 |
-
- Visibility update function for TTS components
|
| 34 |
-
|
| 35 |
-
### 1.2 Settings Flow
|
| 36 |
-
|
| 37 |
-
**Settings → Function Parameters:**
|
| 38 |
-
- Settings from sidebar accordions are passed via `additional_inputs` to `research_agent()` function
|
| 39 |
-
- Hidden textboxes are also passed but use empty strings (converted to None)
|
| 40 |
-
- OAuth token/profile are automatically passed by Gradio
|
| 41 |
-
|
| 42 |
-
**Function Signature (Lines 535-546):**
|
| 43 |
-
```python
|
| 44 |
-
async def research_agent(
|
| 45 |
-
message: str | MultimodalPostprocess,
|
| 46 |
-
history: list[dict[str, Any]],
|
| 47 |
-
mode: str = "simple",
|
| 48 |
-
hf_model: str | None = None,
|
| 49 |
-
hf_provider: str | None = None,
|
| 50 |
-
graph_mode: str = "auto",
|
| 51 |
-
use_graph: bool = True,
|
| 52 |
-
tts_voice: str = "af_heart",
|
| 53 |
-
tts_speed: float = 1.0,
|
| 54 |
-
oauth_token: gr.OAuthToken | None = None,
|
| 55 |
-
oauth_profile: gr.OAuthProfile | None = None,
|
| 56 |
-
)
|
| 57 |
-
```
|
| 58 |
-
|
| 59 |
-
### 1.3 Issues Identified
|
| 60 |
-
|
| 61 |
-
1. **Settings Organization:**
|
| 62 |
-
- Audio output component is in main area, not sidebar
|
| 63 |
-
- Hidden components (hf_model, hf_provider) should be visible or removed
|
| 64 |
-
- No image input enable/disable setting (only audio input has this)
|
| 65 |
-
|
| 66 |
-
2. **Visibility:**
|
| 67 |
-
- Audio output visibility is controlled by checkbox, but component placement is suboptimal
|
| 68 |
-
- TTS settings visibility is controlled by checkbox change event
|
| 69 |
-
|
| 70 |
-
3. **Configuration Gaps:**
|
| 71 |
-
- No `enable_image_input` setting in config (only `enable_audio_input` exists)
|
| 72 |
-
- Image processing always happens if files are present (line 626 comment says "not just when enable_image_input is True" but setting doesn't exist)
|
| 73 |
-
|
| 74 |
-
## 2. Multimodal Input Analysis
|
| 75 |
-
|
| 76 |
-
### 2.1 Current Implementation
|
| 77 |
-
|
| 78 |
-
**ChatInterface Configuration (Line 892-958):**
|
| 79 |
-
- `multimodal=True`: Enables MultimodalTextbox component
|
| 80 |
-
- MultimodalTextbox automatically provides:
|
| 81 |
-
- Text input
|
| 82 |
-
- Image upload button
|
| 83 |
-
- Audio recording button
|
| 84 |
-
- File upload support
|
| 85 |
-
|
| 86 |
-
**Input Processing (Lines 613-642):**
|
| 87 |
-
- Message can be `str` or `MultimodalPostprocess` (dict format)
|
| 88 |
-
- MultimodalPostprocess format: `{"text": str, "files": list[FileData], "audio": tuple | None}`
|
| 89 |
-
- Processing happens in `research_agent()` function:
|
| 90 |
-
- Extracts text, files, and audio from message
|
| 91 |
-
- Calls `multimodal_service.process_multimodal_input()`
|
| 92 |
-
- Condition: `if files or (audio_input_data is not None and settings.enable_audio_input)`
|
| 93 |
-
|
| 94 |
-
**Multimodal Service (src/services/multimodal_processing.py):**
|
| 95 |
-
- Processes audio input if `settings.enable_audio_input` is True
|
| 96 |
-
- Processes image files (no enable/disable check - always processes if files present)
|
| 97 |
-
- Extracts text from images using OCR service
|
| 98 |
-
- Transcribes audio using STT service
|
| 99 |
-
|
| 100 |
-
### 2.2 Gradio Documentation Findings
|
| 101 |
-
|
| 102 |
-
**MultimodalTextbox (ChatInterface with multimodal=True):**
|
| 103 |
-
- Automatically provides image and audio input capabilities
|
| 104 |
-
- Inputs are always visible when ChatInterface is rendered
|
| 105 |
-
- No explicit visibility control needed - it's part of the textbox component
|
| 106 |
-
- Files are handled via `files` array in MultimodalPostprocess
|
| 107 |
-
- Audio recording is handled via `audio` tuple in MultimodalPostprocess
|
| 108 |
-
|
| 109 |
-
**Reference Implementation Pattern:**
|
| 110 |
-
```python
|
| 111 |
-
gr.ChatInterface(
|
| 112 |
-
fn=chat_function,
|
| 113 |
-
multimodal=True, # Enables image/audio inputs
|
| 114 |
-
# ... other parameters
|
| 115 |
-
)
|
| 116 |
-
```
|
| 117 |
-
|
| 118 |
-
### 2.3 Issues Identified
|
| 119 |
-
|
| 120 |
-
1. **Visibility:**
|
| 121 |
-
- Multimodal inputs ARE always visible (they're part of MultimodalTextbox)
|
| 122 |
-
- No explicit control needed - this is working correctly
|
| 123 |
-
- However, users may not realize image/audio inputs are available
|
| 124 |
-
|
| 125 |
-
2. **Configuration:**
|
| 126 |
-
- No `enable_image_input` setting to disable image processing
|
| 127 |
-
- Image processing always happens if files are present
|
| 128 |
-
- Audio processing respects `settings.enable_audio_input`
|
| 129 |
-
|
| 130 |
-
3. **User Experience:**
|
| 131 |
-
- No visual indication that multimodal inputs are available
|
| 132 |
-
- Description mentions "🎤 Multimodal Support" but could be more prominent
|
| 133 |
-
|
| 134 |
-
## 3. File Rendering Analysis
|
| 135 |
-
|
| 136 |
-
### 3.1 Current Implementation
|
| 137 |
-
|
| 138 |
-
**File Detection (Lines 168-195):**
|
| 139 |
-
- `_is_file_path()`: Checks if text looks like a file path
|
| 140 |
-
- Checks for file extensions and path separators
|
| 141 |
-
|
| 142 |
-
**File Rendering in Events (Lines 242-298):**
|
| 143 |
-
- For "complete" events, checks `event.data` for "files" or "file" keys
|
| 144 |
-
- Validates files exist using `os.path.exists()`
|
| 145 |
-
- Formats files as markdown download links: `📎 [Download: filename](filepath)`
|
| 146 |
-
- Stores files in metadata for potential future use
|
| 147 |
-
|
| 148 |
-
**File Links Format:**
|
| 149 |
-
```python
|
| 150 |
-
file_links = "\n\n".join([
|
| 151 |
-
f"📎 [Download: {_get_file_name(f)}]({f})"
|
| 152 |
-
for f in valid_files
|
| 153 |
-
])
|
| 154 |
-
result["content"] = f"{content}\n\n{file_links}"
|
| 155 |
-
```
|
| 156 |
-
|
| 157 |
-
### 3.2 Issues Identified
|
| 158 |
-
|
| 159 |
-
1. **Rendering Method:**
|
| 160 |
-
- Uses markdown links in content string
|
| 161 |
-
- May not work reliably in all Gradio versions
|
| 162 |
-
- Better approach: Use Gradio's native file components or File component
|
| 163 |
-
|
| 164 |
-
2. **File Validation:**
|
| 165 |
-
- Only checks if file exists
|
| 166 |
-
- Doesn't validate file type or size
|
| 167 |
-
- No error handling for inaccessible files
|
| 168 |
-
|
| 169 |
-
3. **User Experience:**
|
| 170 |
-
- Files appear as text links, not as proper file components
|
| 171 |
-
- No preview for images/PDFs
|
| 172 |
-
- No file size information
|
| 173 |
-
|
| 174 |
-
## 4. Implementation Plan
|
| 175 |
-
|
| 176 |
-
### Activity 1: Settings Reorganization
|
| 177 |
-
|
| 178 |
-
**Goal:** Move all settings to sidebar with better organization
|
| 179 |
-
|
| 180 |
-
**File:** `src/app.py`
|
| 181 |
-
|
| 182 |
-
**Tasks:**
|
| 183 |
-
|
| 184 |
-
1. **Move Audio Output Component to Sidebar (Lines 867-887)**
|
| 185 |
-
- Move `audio_output` component into sidebar
|
| 186 |
-
- Place it in Audio Output accordion or create separate section
|
| 187 |
-
- Update visibility logic to work within sidebar
|
| 188 |
-
|
| 189 |
-
2. **Add Image Input Settings (New)**
|
| 190 |
-
- Add `enable_image_input` checkbox to sidebar
|
| 191 |
-
- Create "Image Input" accordion or add to existing "Multimodal Input" accordion
|
| 192 |
-
- Update config to include `enable_image_input` setting
|
| 193 |
-
|
| 194 |
-
3. **Organize Settings Accordions**
|
| 195 |
-
- Research Configuration (existing)
|
| 196 |
-
- Multimodal Input (new - combine image and audio input settings)
|
| 197 |
-
- Audio Output (existing - move component here)
|
| 198 |
-
- Model Configuration (new - for hf_model, hf_provider if we make them visible)
|
| 199 |
-
|
| 200 |
-
**Subtasks:**
|
| 201 |
-
- [ ] Line 867-871: Move `audio_output` component definition into sidebar
|
| 202 |
-
- [ ] Line 873-887: Update visibility update function to work with sidebar placement
|
| 203 |
-
- [ ] Line 798-850: Reorganize Audio Output accordion to include audio_output component
|
| 204 |
-
- [ ] Line 767-796: Keep Research Configuration as-is
|
| 205 |
-
- [ ] After line 796: Add new "Multimodal Input" accordion with enable_image_input and enable_audio_input checkboxes
|
| 206 |
-
- [ ] Line 852-865: Consider making hf_model and hf_provider visible or remove them
|
| 207 |
-
|
| 208 |
-
### Activity 2: Multimodal Input Visibility
|
| 209 |
-
|
| 210 |
-
**Goal:** Ensure multimodal inputs are always visible and well-documented
|
| 211 |
-
|
| 212 |
-
**File:** `src/app.py`
|
| 213 |
-
|
| 214 |
-
**Tasks:**
|
| 215 |
-
|
| 216 |
-
1. **Verify Multimodal Inputs Are Visible**
|
| 217 |
-
- Confirm `multimodal=True` in ChatInterface (already done - line 894)
|
| 218 |
-
- Add visual indicators in description
|
| 219 |
-
- Add tooltips or help text
|
| 220 |
-
|
| 221 |
-
2. **Add Image Input Configuration**
|
| 222 |
-
- Add `enable_image_input` to config (src/utils/config.py)
|
| 223 |
-
- Update multimodal processing to respect this setting
|
| 224 |
-
- Add UI control in sidebar
|
| 225 |
-
|
| 226 |
-
**Subtasks:**
|
| 227 |
-
- [ ] Line 894: Verify `multimodal=True` is set (already correct)
|
| 228 |
-
- [ ] Line 908: Enhance description to highlight multimodal capabilities
|
| 229 |
-
- [ ] src/utils/config.py: Add `enable_image_input: bool = Field(default=True, ...)`
|
| 230 |
-
- [ ] src/services/multimodal_processing.py: Add check for `settings.enable_image_input` before processing images
|
| 231 |
-
- [ ] src/app.py: Add enable_image_input checkbox to sidebar
|
| 232 |
-
|
| 233 |
-
### Activity 3: File Rendering Improvements
|
| 234 |
-
|
| 235 |
-
**Goal:** Improve file rendering using proper Gradio components
|
| 236 |
-
|
| 237 |
-
**File:** `src/app.py`
|
| 238 |
-
|
| 239 |
-
**Tasks:**
|
| 240 |
-
|
| 241 |
-
1. **Improve File Rendering Method**
|
| 242 |
-
- Use Gradio File component or proper file handling
|
| 243 |
-
- Add file previews for images
|
| 244 |
-
- Show file size and type information
|
| 245 |
-
|
| 246 |
-
2. **Enhance File Validation**
|
| 247 |
-
- Validate file types
|
| 248 |
-
- Check file accessibility
|
| 249 |
-
- Handle errors gracefully
|
| 250 |
-
|
| 251 |
-
**Subtasks:**
|
| 252 |
-
- [ ] Line 280-296: Replace markdown link approach with proper file component rendering
|
| 253 |
-
- [ ] Line 168-195: Enhance `_is_file_path()` to validate file types
|
| 254 |
-
- [ ] Line 242-298: Update `event_to_chat_message()` to use Gradio File components
|
| 255 |
-
- [ ] Add file preview functionality for images
|
| 256 |
-
- [ ] Add error handling for inaccessible files
|
| 257 |
-
|
| 258 |
-
### Activity 4: Configuration Updates
|
| 259 |
-
|
| 260 |
-
**Goal:** Add missing configuration settings
|
| 261 |
-
|
| 262 |
-
**File:** `src/utils/config.py`
|
| 263 |
-
|
| 264 |
-
**Tasks:**
|
| 265 |
-
|
| 266 |
-
1. **Add Image Input Setting**
|
| 267 |
-
- Add `enable_image_input` field
|
| 268 |
-
- Add `ocr_api_url` field if missing
|
| 269 |
-
- Add property methods for availability checks
|
| 270 |
-
|
| 271 |
-
**Subtasks:**
|
| 272 |
-
- [ ] After line 147: Add `enable_image_input: bool = Field(default=True, description="Enable image input (OCR) in multimodal interface")`
|
| 273 |
-
- [ ] Check if `ocr_api_url` exists (should be in config)
|
| 274 |
-
- [ ] Add `image_ocr_available` property if missing
|
| 275 |
-
|
| 276 |
-
### Activity 5: Multimodal Service Updates
|
| 277 |
-
|
| 278 |
-
**Goal:** Respect image input enable/disable setting
|
| 279 |
-
|
| 280 |
-
**File:** `src/services/multimodal_processing.py`
|
| 281 |
-
|
| 282 |
-
**Tasks:**
|
| 283 |
-
|
| 284 |
-
1. **Add Image Input Check**
|
| 285 |
-
- Check `settings.enable_image_input` before processing images
|
| 286 |
-
- Log when image processing is skipped due to setting
|
| 287 |
-
|
| 288 |
-
**Subtasks:**
|
| 289 |
-
- [ ] Line 66-77: Add check for `settings.enable_image_input` before processing image files
|
| 290 |
-
- [ ] Add logging when image processing is skipped
|
| 291 |
-
|
| 292 |
-
## 5. Detailed File-Level Tasks
|
| 293 |
-
|
| 294 |
-
### File: `src/app.py`
|
| 295 |
-
|
| 296 |
-
**Line-Level Subtasks:**
|
| 297 |
-
|
| 298 |
-
1. **Lines 741-850: Sidebar Reorganization**
|
| 299 |
-
- [ ] 741-765: Keep authentication and about sections
|
| 300 |
-
- [ ] 767-796: Keep Research Configuration accordion
|
| 301 |
-
- [ ] 797: Add new "Multimodal Input" accordion after Research Configuration
|
| 302 |
-
- [ ] 798-850: Reorganize Audio Output accordion, move audio_output component here
|
| 303 |
-
- [ ] 852-865: Review hidden components - make visible or remove
|
| 304 |
-
|
| 305 |
-
2. **Lines 867-887: Audio Output Component**
|
| 306 |
-
- [ ] 867-871: Move `audio_output` definition into sidebar (Audio Output accordion)
|
| 307 |
-
- [ ] 873-887: Update visibility function to work with sidebar placement
|
| 308 |
-
|
| 309 |
-
3. **Lines 892-958: ChatInterface Configuration**
|
| 310 |
-
- [ ] 894: Verify `multimodal=True` (already correct)
|
| 311 |
-
- [ ] 908: Enhance description with multimodal capabilities
|
| 312 |
-
- [ ] 946-956: Review `additional_inputs` - ensure all settings are included
|
| 313 |
-
|
| 314 |
-
4. **Lines 242-298: File Rendering**
|
| 315 |
-
- [ ] 280-296: Replace markdown links with proper file component rendering
|
| 316 |
-
- [ ] Add file preview for images
|
| 317 |
-
- [ ] Add file size/type information
|
| 318 |
-
|
| 319 |
-
5. **Lines 613-642: Multimodal Input Processing**
|
| 320 |
-
- [ ] 626: Update condition to check `settings.enable_image_input` for files
|
| 321 |
-
- [ ] Add logging for when image processing is skipped
|
| 322 |
-
|
| 323 |
-
### File: `src/utils/config.py`
|
| 324 |
-
|
| 325 |
-
**Line-Level Subtasks:**
|
| 326 |
-
|
| 327 |
-
1. **Lines 143-180: Audio/Image Configuration**
|
| 328 |
-
- [ ] 144-147: `enable_audio_input` exists (keep as-is)
|
| 329 |
-
- [ ] After 147: Add `enable_image_input: bool = Field(default=True, description="Enable image input (OCR) in multimodal interface")`
|
| 330 |
-
- [ ] Check if `ocr_api_url` exists (add if missing)
|
| 331 |
-
- [ ] Add `image_ocr_available` property method
|
| 332 |
-
|
| 333 |
-
### File: `src/services/multimodal_processing.py`
|
| 334 |
-
|
| 335 |
-
**Line-Level Subtasks:**
|
| 336 |
-
|
| 337 |
-
1. **Lines 65-77: Image Processing**
|
| 338 |
-
- [ ] 66: Add check: `if files and settings.enable_image_input:`
|
| 339 |
-
- [ ] 71-77: Keep image processing logic inside the new condition
|
| 340 |
-
- [ ] Add logging when image processing is skipped
|
| 341 |
-
|
| 342 |
-
## 6. Testing Checklist
|
| 343 |
-
|
| 344 |
-
- [ ] Verify all settings are in sidebar
|
| 345 |
-
- [ ] Test multimodal inputs (image upload, audio recording)
|
| 346 |
-
- [ ] Test file rendering (markdown, PDF, images)
|
| 347 |
-
- [ ] Test enable/disable toggles for image and audio inputs
|
| 348 |
-
- [ ] Test audio output generation and display
|
| 349 |
-
- [ ] Test file download links
|
| 350 |
-
- [ ] Verify settings persist across chat sessions
|
| 351 |
-
- [ ] Test on different screen sizes (responsive design)
|
| 352 |
-
|
| 353 |
-
## 7. Implementation Order
|
| 354 |
-
|
| 355 |
-
1. **Phase 1: Configuration** (Foundation)
|
| 356 |
-
- Add `enable_image_input` to config
|
| 357 |
-
- Update multimodal service to respect setting
|
| 358 |
-
|
| 359 |
-
2. **Phase 2: Settings Reorganization** (UI)
|
| 360 |
-
- Move audio output to sidebar
|
| 361 |
-
- Add image input settings to sidebar
|
| 362 |
-
- Organize accordions
|
| 363 |
-
|
| 364 |
-
3. **Phase 3: File Rendering** (Enhancement)
|
| 365 |
-
- Improve file rendering method
|
| 366 |
-
- Add file previews
|
| 367 |
-
- Enhance validation
|
| 368 |
-
|
| 369 |
-
4. **Phase 4: Testing & Refinement** (Quality)
|
| 370 |
-
- Test all functionality
|
| 371 |
-
- Fix any issues
|
| 372 |
-
- Refine UI/UX
|
| 373 |
-
|
| 374 |
-
## 8. Success Criteria
|
| 375 |
-
|
| 376 |
-
- ✅ All settings are in sidebar
|
| 377 |
-
- ✅ Multimodal inputs are always visible and functional
|
| 378 |
-
- ✅ Files are rendered properly with previews
|
| 379 |
-
- ✅ Image and audio input can be enabled/disabled
|
| 380 |
-
- ✅ Settings are well-organized and intuitive
|
| 381 |
-
- ✅ No regressions in existing functionality
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MULTIMODAL_SETTINGS_IMPLEMENTATION_SUMMARY.md
DELETED
|
@@ -1,157 +0,0 @@
|
|
| 1 |
-
# Multimodal Settings & File Rendering - Implementation Summary
|
| 2 |
-
|
| 3 |
-
## ✅ Completed Implementation
|
| 4 |
-
|
| 5 |
-
### 1. Configuration Updates (`src/utils/config.py`)
|
| 6 |
-
|
| 7 |
-
**Added Settings:**
|
| 8 |
-
- ✅ `enable_image_input: bool = Field(default=True, ...)` - Enable/disable image OCR processing
|
| 9 |
-
- ✅ `ocr_api_url: str | None = Field(default="https://prithivmlmods-multimodal-ocr3.hf.space", ...)` - OCR service URL
|
| 10 |
-
|
| 11 |
-
**Location:** Lines 148-156 (after `enable_audio_output`)
|
| 12 |
-
|
| 13 |
-
### 2. Multimodal Service Updates (`src/services/multimodal_processing.py`)
|
| 14 |
-
|
| 15 |
-
**Changes:**
|
| 16 |
-
- ✅ Added check for `settings.enable_image_input` before processing image files
|
| 17 |
-
- ✅ Image processing now respects the enable/disable setting (similar to audio input)
|
| 18 |
-
|
| 19 |
-
**Location:** Line 66 - Added condition: `if files and settings.enable_image_input:`
|
| 20 |
-
|
| 21 |
-
### 3. Sidebar Reorganization (`src/app.py`)
|
| 22 |
-
|
| 23 |
-
**New Accordion: "📷 Multimodal Input"**
|
| 24 |
-
- ✅ Added `enable_image_input_checkbox` - Control image OCR processing
|
| 25 |
-
- ✅ Added `enable_audio_input_checkbox` - Control audio STT processing
|
| 26 |
-
- ✅ Located after "Research Configuration" accordion
|
| 27 |
-
|
| 28 |
-
**Updated Accordion: "🔊 Audio Output"**
|
| 29 |
-
- ✅ Moved `audio_output` component into this accordion (was in main area)
|
| 30 |
-
- ✅ Component now appears in sidebar with other audio settings
|
| 31 |
-
- ✅ Visibility controlled by `enable_audio_output_checkbox`
|
| 32 |
-
|
| 33 |
-
**Settings Organization:**
|
| 34 |
-
1. 🔬 Research Configuration (existing)
|
| 35 |
-
2. 📷 Multimodal Input (NEW)
|
| 36 |
-
3. 🔊 Audio Output (updated - now includes audio_output component)
|
| 37 |
-
|
| 38 |
-
**Location:** Lines 770-850
|
| 39 |
-
|
| 40 |
-
### 4. Function Signature Updates (`src/app.py`)
|
| 41 |
-
|
| 42 |
-
**Updated `research_agent()` function:**
|
| 43 |
-
- ✅ Added `enable_image_input: bool = True` parameter
|
| 44 |
-
- ✅ Added `enable_audio_input: bool = True` parameter
|
| 45 |
-
- ✅ Function now accepts UI settings directly from sidebar checkboxes
|
| 46 |
-
|
| 47 |
-
**Location:** Lines 535-547
|
| 48 |
-
|
| 49 |
-
### 5. Multimodal Input Processing (`src/app.py`)
|
| 50 |
-
|
| 51 |
-
**Updates:**
|
| 52 |
-
- ✅ Uses function parameters (`enable_image_input`, `enable_audio_input`) instead of only config settings
|
| 53 |
-
- ✅ Filters files and audio based on UI settings before processing
|
| 54 |
-
- ✅ More responsive to user changes (no need to restart app)
|
| 55 |
-
|
| 56 |
-
**Location:** Lines 624-636
|
| 57 |
-
|
| 58 |
-
### 6. File Rendering Improvements (`src/app.py`)
|
| 59 |
-
|
| 60 |
-
**Enhancements:**
|
| 61 |
-
- ✅ Added file size display in download links
|
| 62 |
-
- ✅ Better error handling for file size retrieval
|
| 63 |
-
- ✅ Improved formatting with file size information (B, KB, MB)
|
| 64 |
-
|
| 65 |
-
**Location:** Lines 286-300
|
| 66 |
-
|
| 67 |
-
### 7. UI Description Updates (`src/app.py`)
|
| 68 |
-
|
| 69 |
-
**Enhanced Description:**
|
| 70 |
-
- ✅ Better explanation of multimodal capabilities
|
| 71 |
-
- ✅ Clear list of supported input types (Images, Audio, Text)
|
| 72 |
-
- ✅ Reference to sidebar settings for configuration
|
| 73 |
-
|
| 74 |
-
**Location:** Lines 907-912
|
| 75 |
-
|
| 76 |
-
## 📋 Current Settings Structure
|
| 77 |
-
|
| 78 |
-
### Sidebar Layout:
|
| 79 |
-
|
| 80 |
-
```
|
| 81 |
-
🔐 Authentication
|
| 82 |
-
- Login button
|
| 83 |
-
- About section
|
| 84 |
-
|
| 85 |
-
⚙️ Settings
|
| 86 |
-
├─ 🔬 Research Configuration
|
| 87 |
-
│ ├─ Orchestrator Mode
|
| 88 |
-
│ ├─ Graph Research Mode
|
| 89 |
-
│ └─ Use Graph Execution
|
| 90 |
-
│
|
| 91 |
-
├─ 📷 Multimodal Input (NEW)
|
| 92 |
-
│ ├─ Enable Image Input (OCR)
|
| 93 |
-
│ └─ Enable Audio Input (STT)
|
| 94 |
-
│
|
| 95 |
-
└─ 🔊 Audio Output
|
| 96 |
-
├─ Enable Audio Output
|
| 97 |
-
├─ TTS Voice
|
| 98 |
-
├─ TTS Speech Speed
|
| 99 |
-
├─ TTS GPU Type (if Modal available)
|
| 100 |
-
└─ 🔊 Audio Response (moved from main area)
|
| 101 |
-
```
|
| 102 |
-
|
| 103 |
-
## 🔍 Key Features
|
| 104 |
-
|
| 105 |
-
### Multimodal Inputs (Always Visible)
|
| 106 |
-
- **Image Upload**: Available in ChatInterface textbox (multimodal=True)
|
| 107 |
-
- **Audio Recording**: Available in ChatInterface textbox (multimodal=True)
|
| 108 |
-
- **File Upload**: Supported via MultimodalTextbox
|
| 109 |
-
- **Visibility**: Always visible - part of ChatInterface component
|
| 110 |
-
- **Control**: Can be enabled/disabled via sidebar settings
|
| 111 |
-
|
| 112 |
-
### File Rendering
|
| 113 |
-
- **Method**: Markdown download links in chat content
|
| 114 |
-
- **Format**: `📎 [Download: filename (size)](filepath)`
|
| 115 |
-
- **Validation**: Checks file existence before rendering
|
| 116 |
-
- **Metadata**: Files stored in message metadata for future use
|
| 117 |
-
|
| 118 |
-
### Settings Flow
|
| 119 |
-
1. User changes settings in sidebar checkboxes
|
| 120 |
-
2. Settings passed to `research_agent()` via `additional_inputs`
|
| 121 |
-
3. Function uses UI settings (with config defaults as fallback)
|
| 122 |
-
4. Multimodal processing respects enable/disable flags
|
| 123 |
-
5. Settings persist during chat session
|
| 124 |
-
|
| 125 |
-
## 🧪 Testing Checklist
|
| 126 |
-
|
| 127 |
-
- [ ] Verify all settings are in sidebar
|
| 128 |
-
- [ ] Test image upload with OCR enabled/disabled
|
| 129 |
-
- [ ] Test audio recording with STT enabled/disabled
|
| 130 |
-
- [ ] Test file rendering (markdown, PDF, images)
|
| 131 |
-
- [ ] Test audio output generation and display in sidebar
|
| 132 |
-
- [ ] Test file download links
|
| 133 |
-
- [ ] Verify settings work without requiring app restart
|
| 134 |
-
- [ ] Test on different screen sizes (responsive design)
|
| 135 |
-
|
| 136 |
-
## 📝 Notes
|
| 137 |
-
|
| 138 |
-
1. **Multimodal Inputs Visibility**: The inputs are always visible because they're part of the `MultimodalTextbox` component when `multimodal=True` is set in ChatInterface. No additional visibility control is needed.
|
| 139 |
-
|
| 140 |
-
2. **Settings Persistence**: Settings are passed via function parameters, so they persist during the chat session but reset when the app restarts. For persistent settings across sessions, consider using Gradio's state management or session storage.
|
| 141 |
-
|
| 142 |
-
3. **File Rendering**: Gradio ChatInterface automatically handles markdown file links. The current implementation with file size information should work well. For more advanced file previews, consider using Gradio's File component in a custom Blocks layout.
|
| 143 |
-
|
| 144 |
-
4. **Hidden Components**: The `hf_model_dropdown` and `hf_provider_dropdown` are still hidden. Consider making them visible in a "Model Configuration" accordion if needed, or remove them if not used.
|
| 145 |
-
|
| 146 |
-
## 🚀 Next Steps (Optional Enhancements)
|
| 147 |
-
|
| 148 |
-
1. **Model Configuration Accordion**: Make hf_model and hf_provider visible in sidebar
|
| 149 |
-
2. **File Previews**: Add image previews for uploaded images in chat
|
| 150 |
-
3. **Settings Persistence**: Implement session-based settings storage
|
| 151 |
-
4. **Advanced File Rendering**: Use Gradio File component for better file handling
|
| 152 |
-
5. **Error Handling**: Add better error messages for failed file operations
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Makefile
DELETED
|
@@ -1,42 +0,0 @@
|
|
| 1 |
-
.PHONY: install test lint format typecheck check clean all cov cov-html
|
| 2 |
-
|
| 3 |
-
# Default target
|
| 4 |
-
all: check
|
| 5 |
-
|
| 6 |
-
install:
|
| 7 |
-
uv sync --all-extras
|
| 8 |
-
uv run pre-commit install
|
| 9 |
-
|
| 10 |
-
test:
|
| 11 |
-
uv run pytest tests/unit/ -v -m "not openai" -p no:logfire
|
| 12 |
-
|
| 13 |
-
test-hf:
|
| 14 |
-
uv run pytest tests/ -v -m "huggingface" -p no:logfire
|
| 15 |
-
|
| 16 |
-
test-all:
|
| 17 |
-
uv run pytest tests/ -v -p no:logfire
|
| 18 |
-
|
| 19 |
-
# Coverage aliases
|
| 20 |
-
cov: test-cov
|
| 21 |
-
test-cov:
|
| 22 |
-
uv run pytest --cov=src --cov-report=term-missing -m "not openai" -p no:logfire
|
| 23 |
-
|
| 24 |
-
cov-html:
|
| 25 |
-
uv run pytest --cov=src --cov-report=html -p no:logfire
|
| 26 |
-
@echo "Coverage report: open htmlcov/index.html"
|
| 27 |
-
|
| 28 |
-
lint:
|
| 29 |
-
uv run ruff check src tests
|
| 30 |
-
|
| 31 |
-
format:
|
| 32 |
-
uv run ruff format src tests
|
| 33 |
-
|
| 34 |
-
typecheck:
|
| 35 |
-
uv run mypy src
|
| 36 |
-
|
| 37 |
-
check: lint typecheck test-cov
|
| 38 |
-
@echo "All checks passed!"
|
| 39 |
-
|
| 40 |
-
clean:
|
| 41 |
-
rm -rf .pytest_cache .mypy_cache .ruff_cache __pycache__ .coverage htmlcov
|
| 42 |
-
find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PDF_REPORT_INTEGRATION.md
DELETED
|
@@ -1,134 +0,0 @@
|
|
| 1 |
-
# PDF Report Generation Integration
|
| 2 |
-
|
| 3 |
-
## Summary
|
| 4 |
-
|
| 5 |
-
Integrated PDF generation functionality into the report file service using utilities from `folder/utils copy`. Reports can now be automatically converted to PDF format as a final step.
|
| 6 |
-
|
| 7 |
-
## Changes Made
|
| 8 |
-
|
| 9 |
-
### 1. Added PDF Conversion Utilities
|
| 10 |
-
|
| 11 |
-
**Files Created:**
|
| 12 |
-
- `src/utils/md_to_pdf.py` - Markdown to PDF conversion utility
|
| 13 |
-
- `src/utils/markdown.css` - CSS styling for PDF output
|
| 14 |
-
|
| 15 |
-
**Features:**
|
| 16 |
-
- Uses `md2pdf` library for conversion
|
| 17 |
-
- Includes error handling and graceful fallback
|
| 18 |
-
- Supports custom CSS styling
|
| 19 |
-
- Logs conversion status
|
| 20 |
-
|
| 21 |
-
### 2. Enhanced ReportFileService
|
| 22 |
-
|
| 23 |
-
**File:** `src/services/report_file_service.py`
|
| 24 |
-
|
| 25 |
-
**Changes:**
|
| 26 |
-
- Added `_save_pdf()` method to generate PDF from markdown
|
| 27 |
-
- Updated `save_report_multiple_formats()` to implement PDF generation
|
| 28 |
-
- PDF is generated when `report_file_format` is set to `"md_pdf"`
|
| 29 |
-
- Both markdown and PDF files are saved and returned
|
| 30 |
-
|
| 31 |
-
**Method Signature:**
|
| 32 |
-
```python
|
| 33 |
-
def _save_pdf(
|
| 34 |
-
self,
|
| 35 |
-
report_content: str,
|
| 36 |
-
query: str | None = None,
|
| 37 |
-
) -> str:
|
| 38 |
-
"""Save report as PDF. Returns path to PDF file."""
|
| 39 |
-
```
|
| 40 |
-
|
| 41 |
-
### 3. Updated Graph Orchestrator
|
| 42 |
-
|
| 43 |
-
**File:** `src/orchestrator/graph_orchestrator.py`
|
| 44 |
-
|
| 45 |
-
**Changes:**
|
| 46 |
-
- Updated synthesizer node to use `save_report_multiple_formats()`
|
| 47 |
-
- Updated writer node to use `save_report_multiple_formats()`
|
| 48 |
-
- Both nodes now return PDF paths in result dict when available
|
| 49 |
-
- Result includes both `file` (markdown) and `files` (both formats) keys
|
| 50 |
-
|
| 51 |
-
**Result Format:**
|
| 52 |
-
```python
|
| 53 |
-
{
|
| 54 |
-
"message": final_report, # Report content
|
| 55 |
-
"file": "/path/to/report.md", # Markdown file
|
| 56 |
-
"files": ["/path/to/report.md", "/path/to/report.pdf"] # Both formats
|
| 57 |
-
}
|
| 58 |
-
```
|
| 59 |
-
|
| 60 |
-
## Configuration
|
| 61 |
-
|
| 62 |
-
PDF generation is controlled by the `report_file_format` setting in `src/utils/config.py`:
|
| 63 |
-
|
| 64 |
-
```python
|
| 65 |
-
report_file_format: Literal["md", "md_html", "md_pdf"] = Field(
|
| 66 |
-
default="md",
|
| 67 |
-
description="File format(s) to save reports in."
|
| 68 |
-
)
|
| 69 |
-
```
|
| 70 |
-
|
| 71 |
-
**Options:**
|
| 72 |
-
- `"md"` - Save only markdown (default)
|
| 73 |
-
- `"md_html"` - Save markdown + HTML (not yet implemented)
|
| 74 |
-
- `"md_pdf"` - Save markdown + PDF ✅ **Now implemented**
|
| 75 |
-
|
| 76 |
-
## Usage
|
| 77 |
-
|
| 78 |
-
### Enable PDF Generation
|
| 79 |
-
|
| 80 |
-
Set the environment variable or update settings:
|
| 81 |
-
```bash
|
| 82 |
-
REPORT_FILE_FORMAT=md_pdf
|
| 83 |
-
```
|
| 84 |
-
|
| 85 |
-
Or in code:
|
| 86 |
-
```python
|
| 87 |
-
from src.utils.config import settings
|
| 88 |
-
settings.report_file_format = "md_pdf"
|
| 89 |
-
```
|
| 90 |
-
|
| 91 |
-
### Dependencies
|
| 92 |
-
|
| 93 |
-
PDF generation requires the `md2pdf` library:
|
| 94 |
-
```bash
|
| 95 |
-
pip install md2pdf
|
| 96 |
-
```
|
| 97 |
-
|
| 98 |
-
If `md2pdf` is not installed, the system will:
|
| 99 |
-
- Log a warning
|
| 100 |
-
- Continue with markdown-only saving
|
| 101 |
-
- Not fail the report generation
|
| 102 |
-
|
| 103 |
-
## File Output
|
| 104 |
-
|
| 105 |
-
When PDF generation is enabled:
|
| 106 |
-
1. Markdown file is always saved first
|
| 107 |
-
2. PDF is generated from the markdown content
|
| 108 |
-
3. Both file paths are returned in the result
|
| 109 |
-
4. Gradio interface can display/download both files
|
| 110 |
-
|
| 111 |
-
## Error Handling
|
| 112 |
-
|
| 113 |
-
- If PDF generation fails, markdown file is still saved
|
| 114 |
-
- Errors are logged but don't interrupt report generation
|
| 115 |
-
- Graceful fallback ensures reports are always available
|
| 116 |
-
|
| 117 |
-
## Integration Points
|
| 118 |
-
|
| 119 |
-
PDF generation is automatically triggered when:
|
| 120 |
-
1. Graph orchestrator synthesizer node completes
|
| 121 |
-
2. Graph orchestrator writer node completes
|
| 122 |
-
3. `save_report_multiple_formats()` is called
|
| 123 |
-
4. `report_file_format` is set to `"md_pdf"`
|
| 124 |
-
|
| 125 |
-
## Future Enhancements
|
| 126 |
-
|
| 127 |
-
- HTML format support (`md_html`)
|
| 128 |
-
- Custom PDF templates
|
| 129 |
-
- PDF metadata (title, author, keywords)
|
| 130 |
-
- PDF compression options
|
| 131 |
-
- Batch PDF generation
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README.md
CHANGED
|
@@ -34,16 +34,15 @@ tags:
|
|
| 34 |
> [!IMPORTANT]
|
| 35 |
> **You are reading the Gradio Demo README!**
|
| 36 |
>
|
| 37 |
-
> - 📚 **Documentation**: See our [technical documentation](deepcritical.github.io/GradioDemo/) for detailed information
|
| 38 |
-
> - 📖 **Complete README**: Check out the [
|
| 39 |
-
> -
|
| 40 |
|
| 41 |
<div align="center">
|
| 42 |
|
| 43 |
[](https://github.com/DeepCritical/GradioDemo)
|
| 44 |
[](deepcritical.github.io/GradioDemo/)
|
| 45 |
[](https://huggingface.co/spaces/DataQuests/DeepCritical)
|
| 46 |
-
[](https://www.youtube.com/watch?v=https://youtu.be/Mb0M83BqgOw)
|
| 47 |
[](https://codecov.io/gh/DeepCritical/GradioDemo)
|
| 48 |
[](https://discord.gg/qdfnvSPcqP)
|
| 49 |
|
|
@@ -55,147 +54,3 @@ tags:
|
|
| 55 |
## About
|
| 56 |
|
| 57 |
The DETERMINATOR is a powerful generalist deep research agent system that stops at nothing until finding precise answers to complex questions. It uses iterative search-and-judge loops to comprehensively investigate any research question from any domain.
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
> For this hackathon we're proposing a simple yet powerful Deep Research Agent that iteratively looks for the answer until it finds it using general purpose websearch and special purpose retrievers for technical retrievers.
|
| 61 |
-
|
| 62 |
-
## Who We Are & Motivation
|
| 63 |
-
|
| 64 |
-
We're a group from the `DeepCritical` Group that met in the `hugging-science` discord.
|
| 65 |
-
|
| 66 |
-
We're enthusiastic about strongly typed and robust pythonic agentic frameworks , currently building ai-assisted multi-agent systems for research automations , like critical literature reviews , clinical data retrival , and bio informatics and computational medicine applications .
|
| 67 |
-
|
| 68 |
-
Starting from Magentic Design Patterns for agentic systems , we discovered we could get better results with iterative graphs , orchestrators and planners with magentic agentics as single tools inside iterations.
|
| 69 |
-
|
| 70 |
-
## Do You Like This App ?
|
| 71 |
-
|
| 72 |
-
Please join us @ https://hf.co/spaces/DataQuests/DeepCritical where we will keep maintaining it !
|
| 73 |
-
|
| 74 |
-
## The DETERMINATOR is Lightweight and POWERFUL
|
| 75 |
-
|
| 76 |
-
- very accessible (multimodal inputs , audio and text out)
|
| 77 |
-
- fully local embeddings
|
| 78 |
-
- configurable providers (local/hosted) for websearch
|
| 79 |
-
- all data stays local
|
| 80 |
-
- fully configurable models and huggingface providers with login
|
| 81 |
-
- easily extensible and hackable
|
| 82 |
-
- uses Gradio a lot (clients, mcp , third party huggingface tools)
|
| 83 |
-
- Modal for text-to-speech (remote gpu for "local model")
|
| 84 |
-
- Braxel for statistical analysis (code execution sandbox)
|
| 85 |
-
- Open Source Models from around the 🌐World
|
| 86 |
-
- Using Google Gemma , Qwen , Zai , Llama , Mistral Reasoning Models
|
| 87 |
-
- Nebius , Together , Scaleway , Hyperbolic, Novita , nscale , Sambanova , ovh , fireworks, all supported and configurable.
|
| 88 |
-
- 💖 made with love
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
## What Can It Do ?
|
| 92 |
-
|
| 93 |
-
- long running tasks (potentially millions of tokens over hours and hours)
|
| 94 |
-
- data processing and rendering
|
| 95 |
-
- statistical analyses
|
| 96 |
-
- literature reviews
|
| 97 |
-
- websearch
|
| 98 |
-
- synthetize complex information
|
| 99 |
-
- find hard to find information
|
| 100 |
-
|
| 101 |
-
## Deep Critical In the Media
|
| 102 |
-
|
| 103 |
-
- Social Medial Posts about Deep Critical :
|
| 104 |
-
- 𝕏 []
|
| 105 |
-
- 💼 []
|
| 106 |
-
- 𝕏 []
|
| 107 |
-
|
| 108 |
-
-💼 [
|
| 109 |
-
-
|
| 110 |
-
-
|
| 111 |
-
|
| 112 |
-
> [!IMPORTANT]
|
| 113 |
-
> **IF YOU ARE A JUDGE**
|
| 114 |
-
>
|
| 115 |
-
> This project was produced with passion by a group of volunteers please check out or documentation and readmes and please do keep reading below for our story
|
| 116 |
-
>
|
| 117 |
-
> - 📚 **Documentation**: See our [technical documentation](https://deepcritical.github.io/GradioDemo/) for detailed information
|
| 118 |
-
> - 📖 **Complete README**: Check out the Github [full README](.github/README.md) for setup, configuration, and contribution guidelines
|
| 119 |
-
> - 🏆 **Hackathon Submission**: Keep reading below for more information about our MCP Hackathon submission
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
**Key Features**:
|
| 123 |
-
- **Generalist**: Handles queries from any domain (medical, technical, business, scientific, etc.)
|
| 124 |
-
- **Automatic Medical Detection**: Automatically determines if medical knowledge sources (PubMed, ClinicalTrials.gov) are needed
|
| 125 |
-
- **Multi-Source Search**: Web search, PubMed, ClinicalTrials.gov, Europe PMC, RAG
|
| 126 |
-
- **Stops at Nothing**: Only stops at configured limits (budget, time, iterations), otherwise continues until finding precise answers
|
| 127 |
-
- **Evidence Synthesis**: Comprehensive reports with proper citations
|
| 128 |
-
|
| 129 |
-
**Important**: The DETERMINATOR is a research tool that synthesizes evidence. It cannot provide medical advice or answer medical questions directly.
|
| 130 |
-
|
| 131 |
-
## Important information
|
| 132 |
-
|
| 133 |
-
- **[readme](.github\README.md)**: configure, deploy , contribute and learn more here.
|
| 134 |
-
- **[docs](deepcritical.github.io/GradioDemo/)**: want to know how all this works ? read our detailed technical documentation here.
|
| 135 |
-
- **[demo](https://huggingface/spaces/DataQuests/DeepCritical)**: Try our demo on huggingface
|
| 136 |
-
- **[team](### Team)**: Join us , or follow us !
|
| 137 |
-
- **[video]**: See our demo video
|
| 138 |
-
|
| 139 |
-
## Future Developments
|
| 140 |
-
|
| 141 |
-
- [] Apply Deep Research Systems To Generate Short Form Video (up to 5 minutes)
|
| 142 |
-
- [] Visualize Pydantic Graphs as Loading Screens in the UI
|
| 143 |
-
- [] Improve Data Science with more Complex Graph Agents
|
| 144 |
-
- [] Create Deep Critical Drug Reporposing / Discovery Demo
|
| 145 |
-
- [] Create Deep Critical Literal Review
|
| 146 |
-
- [] Create Deep Critical Hypothesis Generator
|
| 147 |
-
- [] Create PyPi Package
|
| 148 |
-
|
| 149 |
-
## Completed
|
| 150 |
-
|
| 151 |
-
- [x] **Multi-Source Search**: PubMed, ClinicalTrials.gov, bioRxiv/medRxiv
|
| 152 |
-
- [x] **MCP Integration**: Use our tools from Claude Desktop or any MCP client
|
| 153 |
-
- [x] **HuggingFace OAuth**: Sign in with HuggingFace
|
| 154 |
-
- [x] **Modal Sandbox**: Secure execution of AI-generated statistical code
|
| 155 |
-
- [x] **LlamaIndex RAG**: Semantic search and evidence synthesis
|
| 156 |
-
- [x] **HuggingfaceInference**:
|
| 157 |
-
- [x] **HuggingfaceMCP Custom Config To Use Community Tools**:
|
| 158 |
-
- [x] **Strongly Typed Composable Graphs**:
|
| 159 |
-
- [x] **Specialized Research Teams of Agents**:
|
| 160 |
-
|
| 161 |
-
### Team
|
| 162 |
-
- **ZJ**
|
| 163 |
-
- 💼 [LinkedIn](https://www.linkedin.com/in/josephpollack/)
|
| 164 |
-
- **Mario Aderman**
|
| 165 |
-
- 🤗 [HuggingFace](https://huggingface.co/SeasonalFall84)
|
| 166 |
-
- 💼 [LinkedIn](https://www.linkedin.com/in/mario-aderman/)
|
| 167 |
-
- 𝕏 [X](https://x.com/marioaderman)
|
| 168 |
-
- **Joseph Pollack**
|
| 169 |
-
- 🤗 [HuggingFace](https://huggingface.co/Tonic)
|
| 170 |
-
- 💼 [LinkedIn](https://www.linkedin.com/in/josephpollack/)
|
| 171 |
-
- 𝕏 [X](https://x.com/josephpollack)
|
| 172 |
-
- **Virat Chauran**
|
| 173 |
-
- 𝕏 [X](https://x.com/viratzzs/)
|
| 174 |
-
- 💼 [LinkedIn](https://www.linkedin.com/in/viratchauhan/)
|
| 175 |
-
- 🤗 [HuggingFace](https://huggingface.co/ViratChauhan)
|
| 176 |
-
- **Anna Bossler**
|
| 177 |
-
- 💼 [LinkedIn](https://www.linkedin.com/in/ana-bossler-07304717)
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
## Acknowledgements
|
| 181 |
-
|
| 182 |
-
- [DeepBoner](https://hf.co/spaces/mcp-1st-birthday/deepboner)
|
| 183 |
-
- Magentic Paper
|
| 184 |
-
- [Huggingface](https://hf.co)
|
| 185 |
-
- [Gradio](https://gradio.app)
|
| 186 |
-
- [DeepCritical](https://github.com/DeepCritical)
|
| 187 |
-
- [Modal](https://modal.com)
|
| 188 |
-
- Microsoft
|
| 189 |
-
- Pydantic
|
| 190 |
-
- Llama-index
|
| 191 |
-
- Anthhropic/MCP
|
| 192 |
-
- All our Tool Providers
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
## Links
|
| 196 |
-
|
| 197 |
-
[](https://github.com/DeepCritical/GradioDemo)
|
| 198 |
-
[](deepcritical.github.io/GradioDemo/)
|
| 199 |
-
[](https://huggingface.co/spaces/DataQuests/DeepCritical)
|
| 200 |
-
[](https://codecov.io/gh/DeepCritical/GradioDemo)
|
| 201 |
-
[](https://discord.gg/qdfnvSPcqP)
|
|
|
|
| 34 |
> [!IMPORTANT]
|
| 35 |
> **You are reading the Gradio Demo README!**
|
| 36 |
>
|
| 37 |
+
> - 📚 **Documentation**: See our [technical documentation](https://deepcritical.github.io/GradioDemo/) for detailed information
|
| 38 |
+
> - 📖 **Complete README**: Check out the [Github README](.github/README.md) for setup, configuration, and contribution guidelines
|
| 39 |
+
> - ⚠️**This README is for our Gradio Demo Only !**
|
| 40 |
|
| 41 |
<div align="center">
|
| 42 |
|
| 43 |
[](https://github.com/DeepCritical/GradioDemo)
|
| 44 |
[](deepcritical.github.io/GradioDemo/)
|
| 45 |
[](https://huggingface.co/spaces/DataQuests/DeepCritical)
|
|
|
|
| 46 |
[](https://codecov.io/gh/DeepCritical/GradioDemo)
|
| 47 |
[](https://discord.gg/qdfnvSPcqP)
|
| 48 |
|
|
|
|
| 54 |
## About
|
| 55 |
|
| 56 |
The DETERMINATOR is a powerful generalist deep research agent system that stops at nothing until finding precise answers to complex questions. It uses iterative search-and-judge loops to comprehensively investigate any research question from any domain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
REPORT_WRITING_AGENTS_ANALYSIS.md
DELETED
|
@@ -1,189 +0,0 @@
|
|
| 1 |
-
# Report Writing Agents Analysis
|
| 2 |
-
|
| 3 |
-
## Summary
|
| 4 |
-
|
| 5 |
-
This document identifies all agents and methods in the repository that generate reports or write to files.
|
| 6 |
-
|
| 7 |
-
## Key Finding
|
| 8 |
-
|
| 9 |
-
**All report-writing agents return strings (markdown) - NONE write directly to files.**
|
| 10 |
-
|
| 11 |
-
The agents generate report content but do not save it to disk. File writing would need to be added as a separate step.
|
| 12 |
-
|
| 13 |
-
---
|
| 14 |
-
|
| 15 |
-
## Report Writing Agents
|
| 16 |
-
|
| 17 |
-
### 1. WriterAgent
|
| 18 |
-
**File**: `src/agents/writer.py`
|
| 19 |
-
|
| 20 |
-
**Method**: `async def write_report(query, findings, output_length, output_instructions) -> str`
|
| 21 |
-
|
| 22 |
-
**Returns**: Markdown formatted report string
|
| 23 |
-
|
| 24 |
-
**Purpose**: Generates final reports from research findings with numbered citations
|
| 25 |
-
|
| 26 |
-
**File Writing**: ❌ **NO** - Returns string only
|
| 27 |
-
|
| 28 |
-
**Key Features**:
|
| 29 |
-
- Validates inputs
|
| 30 |
-
- Truncates very long findings (max 50,000 chars)
|
| 31 |
-
- Retry logic (3 retries)
|
| 32 |
-
- Returns markdown with numbered citations
|
| 33 |
-
|
| 34 |
-
---
|
| 35 |
-
|
| 36 |
-
### 2. LongWriterAgent
|
| 37 |
-
**File**: `src/agents/long_writer.py`
|
| 38 |
-
|
| 39 |
-
**Methods**:
|
| 40 |
-
- `async def write_next_section(original_query, report_draft, next_section_title, next_section_draft) -> LongWriterOutput`
|
| 41 |
-
- `async def write_report(original_query, report_title, report_draft) -> str`
|
| 42 |
-
|
| 43 |
-
**Returns**:
|
| 44 |
-
- `write_next_section()`: `LongWriterOutput` object (structured output)
|
| 45 |
-
- `write_report()`: Complete markdown report string
|
| 46 |
-
|
| 47 |
-
**Purpose**: Iteratively writes report sections with proper citations and reference management
|
| 48 |
-
|
| 49 |
-
**File Writing**: ❌ **NO** - Returns string only
|
| 50 |
-
|
| 51 |
-
**Key Features**:
|
| 52 |
-
- Writes sections iteratively
|
| 53 |
-
- Reformats and deduplicates references
|
| 54 |
-
- Adjusts heading levels
|
| 55 |
-
- Aggregates references across sections
|
| 56 |
-
|
| 57 |
-
---
|
| 58 |
-
|
| 59 |
-
### 3. ProofreaderAgent
|
| 60 |
-
**File**: `src/agents/proofreader.py`
|
| 61 |
-
|
| 62 |
-
**Method**: `async def proofread(query, report_draft) -> str`
|
| 63 |
-
|
| 64 |
-
**Returns**: Final polished markdown report string
|
| 65 |
-
|
| 66 |
-
**Purpose**: Proofreads and finalizes report drafts
|
| 67 |
-
|
| 68 |
-
**File Writing**: ❌ **NO** - Returns string only
|
| 69 |
-
|
| 70 |
-
**Key Features**:
|
| 71 |
-
- Combines sections
|
| 72 |
-
- Removes duplicates
|
| 73 |
-
- Adds summary
|
| 74 |
-
- Preserves references
|
| 75 |
-
- Polishes wording
|
| 76 |
-
|
| 77 |
-
---
|
| 78 |
-
|
| 79 |
-
### 4. ReportAgent
|
| 80 |
-
**File**: `src/agents/report_agent.py`
|
| 81 |
-
|
| 82 |
-
**Method**: `async def run(messages, thread, **kwargs) -> AgentRunResponse`
|
| 83 |
-
|
| 84 |
-
**Returns**: `AgentRunResponse` with markdown text in `messages[0].text`
|
| 85 |
-
|
| 86 |
-
**Purpose**: Generates structured scientific reports from evidence and hypotheses
|
| 87 |
-
|
| 88 |
-
**File Writing**: ❌ **NO** - Returns `AgentRunResponse` object
|
| 89 |
-
|
| 90 |
-
**Key Features**:
|
| 91 |
-
- Uses structured `ResearchReport` model
|
| 92 |
-
- Validates citations
|
| 93 |
-
- Returns markdown via `report.to_markdown()`
|
| 94 |
-
|
| 95 |
-
---
|
| 96 |
-
|
| 97 |
-
## File Writing Operations Found
|
| 98 |
-
|
| 99 |
-
### Temporary File Writing (Not Reports)
|
| 100 |
-
|
| 101 |
-
1. **ImageOCRService** (`src/services/image_ocr.py`)
|
| 102 |
-
- `_save_image_temp(image) -> str`
|
| 103 |
-
- Saves temporary images for OCR processing
|
| 104 |
-
- Returns temp file path
|
| 105 |
-
|
| 106 |
-
2. **STTService** (`src/services/stt_gradio.py`)
|
| 107 |
-
- `_save_audio_temp(audio_array, sample_rate) -> str`
|
| 108 |
-
- Saves temporary audio files for transcription
|
| 109 |
-
- Returns temp file path
|
| 110 |
-
|
| 111 |
-
---
|
| 112 |
-
|
| 113 |
-
## Where Reports Are Used
|
| 114 |
-
|
| 115 |
-
### Graph Orchestrator
|
| 116 |
-
**File**: `src/orchestrator/graph_orchestrator.py`
|
| 117 |
-
|
| 118 |
-
- Line 642: `final_report = await long_writer_agent.write_report(...)`
|
| 119 |
-
- Returns string result, stored in graph context
|
| 120 |
-
- Final result passed through `AgentEvent` with `message` field
|
| 121 |
-
|
| 122 |
-
### Research Flows
|
| 123 |
-
**File**: `src/orchestrator/research_flow.py`
|
| 124 |
-
|
| 125 |
-
- `IterativeResearchFlow._create_final_report()`: Calls `writer_agent.write_report()`
|
| 126 |
-
- `DeepResearchFlow._create_final_report()`: Calls `long_writer_agent.write_report()`
|
| 127 |
-
- Both return strings
|
| 128 |
-
|
| 129 |
-
---
|
| 130 |
-
|
| 131 |
-
## Integration Points for File Writing
|
| 132 |
-
|
| 133 |
-
To add file writing capability, you would need to:
|
| 134 |
-
|
| 135 |
-
1. **After report generation**: Save the returned string to a file
|
| 136 |
-
2. **In graph orchestrator**: After `write_report()`, save to file and include path in result
|
| 137 |
-
3. **In research flows**: After `_create_final_report()`, save to file
|
| 138 |
-
|
| 139 |
-
### Example Implementation Pattern
|
| 140 |
-
|
| 141 |
-
```python
|
| 142 |
-
import tempfile
|
| 143 |
-
from pathlib import Path
|
| 144 |
-
|
| 145 |
-
# After report generation
|
| 146 |
-
report_content = await writer_agent.write_report(...)
|
| 147 |
-
|
| 148 |
-
# Save to file
|
| 149 |
-
output_dir = Path("/tmp/reports") # or configurable
|
| 150 |
-
output_dir.mkdir(exist_ok=True)
|
| 151 |
-
file_path = output_dir / f"report_{timestamp}.md"
|
| 152 |
-
|
| 153 |
-
with open(file_path, "w", encoding="utf-8") as f:
|
| 154 |
-
f.write(report_content)
|
| 155 |
-
|
| 156 |
-
# Return both content and file path
|
| 157 |
-
return {
|
| 158 |
-
"message": "Report generated successfully",
|
| 159 |
-
"file": str(file_path)
|
| 160 |
-
}
|
| 161 |
-
```
|
| 162 |
-
|
| 163 |
-
---
|
| 164 |
-
|
| 165 |
-
## Recommendations
|
| 166 |
-
|
| 167 |
-
1. **Add file writing utility**: Create a helper function to save reports to files
|
| 168 |
-
2. **Make it optional**: Add configuration flag to enable/disable file saving
|
| 169 |
-
3. **Use temp directory**: Save to temp directory by default, allow custom path
|
| 170 |
-
4. **Include in graph results**: Modify graph orchestrator to optionally save and return file paths
|
| 171 |
-
5. **Support multiple formats**: Consider saving as both `.md` and potentially `.pdf` or `.html`
|
| 172 |
-
|
| 173 |
-
---
|
| 174 |
-
|
| 175 |
-
## Current State
|
| 176 |
-
|
| 177 |
-
✅ **Report Generation**: Fully implemented
|
| 178 |
-
❌ **File Writing**: Not implemented
|
| 179 |
-
✅ **File Output Integration**: Recently added (see previous work on `event_to_chat_message`)
|
| 180 |
-
|
| 181 |
-
The infrastructure to handle file outputs in Gradio is in place, but the agents themselves do not yet write files. They would need to be enhanced or wrapped to add file writing capability.
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SERPER_WEBSEARCH_IMPLEMENTATION_PLAN.md
DELETED
|
@@ -1,403 +0,0 @@
|
|
| 1 |
-
# SERPER Web Search Implementation Plan
|
| 2 |
-
|
| 3 |
-
## Executive Summary
|
| 4 |
-
|
| 5 |
-
This plan details the implementation of SERPER-based web search by vendoring code from `folder/tools/web_search.py` into `src/tools/`, creating a protocol-compliant `SerperWebSearchTool`, fixing the existing `WebSearchTool`, and integrating both into the main search flow.
|
| 6 |
-
|
| 7 |
-
## Project Structure
|
| 8 |
-
|
| 9 |
-
### Project 1: Vendor and Refactor Core Web Search Components
|
| 10 |
-
**Goal**: Extract and vendor Serper/SearchXNG search logic from `folder/tools/web_search.py` into `src/tools/`
|
| 11 |
-
|
| 12 |
-
### Project 2: Create Protocol-Compliant SerperWebSearchTool
|
| 13 |
-
**Goal**: Implement `SerperWebSearchTool` class that fully complies with `SearchTool` protocol
|
| 14 |
-
|
| 15 |
-
### Project 3: Fix Existing WebSearchTool Protocol Compliance
|
| 16 |
-
**Goal**: Make existing `WebSearchTool` (DuckDuckGo) protocol-compliant
|
| 17 |
-
|
| 18 |
-
### Project 4: Integrate Web Search into SearchHandler
|
| 19 |
-
**Goal**: Add web search tools to main search flow in `src/app.py`
|
| 20 |
-
|
| 21 |
-
### Project 5: Update Callers and Dependencies
|
| 22 |
-
**Goal**: Update all code that uses web search to work with new implementation
|
| 23 |
-
|
| 24 |
-
### Project 6: Testing and Validation
|
| 25 |
-
**Goal**: Add comprehensive tests for all web search implementations
|
| 26 |
-
|
| 27 |
-
---
|
| 28 |
-
|
| 29 |
-
## Detailed Implementation Plan
|
| 30 |
-
|
| 31 |
-
### PROJECT 1: Vendor and Refactor Core Web Search Components
|
| 32 |
-
|
| 33 |
-
#### Activity 1.1: Create Vendor Module Structure
|
| 34 |
-
**File**: `src/tools/vendored/__init__.py`
|
| 35 |
-
- **Task 1.1.1**: Create `src/tools/vendored/` directory
|
| 36 |
-
- **Task 1.1.2**: Create `__init__.py` with exports
|
| 37 |
-
|
| 38 |
-
**File**: `src/tools/vendored/web_search_core.py`
|
| 39 |
-
- **Task 1.1.3**: Vendor `ScrapeResult`, `WebpageSnippet`, `SearchResults` models from `folder/tools/web_search.py` (lines 23-37)
|
| 40 |
-
- **Task 1.1.4**: Vendor `scrape_urls()` function (lines 274-299)
|
| 41 |
-
- **Task 1.1.5**: Vendor `fetch_and_process_url()` function (lines 302-348)
|
| 42 |
-
- **Task 1.1.6**: Vendor `html_to_text()` function (lines 351-368)
|
| 43 |
-
- **Task 1.1.7**: Vendor `is_valid_url()` function (lines 371-410)
|
| 44 |
-
- **Task 1.1.8**: Vendor `ssl_context` setup (lines 115-120)
|
| 45 |
-
- **Task 1.1.9**: Add imports: `aiohttp`, `asyncio`, `BeautifulSoup`, `ssl`
|
| 46 |
-
- **Task 1.1.10**: Add `CONTENT_LENGTH_LIMIT = 10000` constant
|
| 47 |
-
- **Task 1.1.11**: Add type hints following project standards
|
| 48 |
-
- **Task 1.1.12**: Add structlog logging
|
| 49 |
-
- **Task 1.1.13**: Replace `print()` statements with `logger` calls
|
| 50 |
-
|
| 51 |
-
**File**: `src/tools/vendored/serper_client.py`
|
| 52 |
-
- **Task 1.1.14**: Vendor `SerperClient` class from `folder/tools/web_search.py` (lines 123-196)
|
| 53 |
-
- **Task 1.1.15**: Remove dependency on `ResearchAgent` and `ResearchRunner`
|
| 54 |
-
- **Task 1.1.16**: Replace filter agent with simple relevance filtering or remove it
|
| 55 |
-
- **Task 1.1.17**: Add `__init__` that takes `api_key: str | None` parameter
|
| 56 |
-
- **Task 1.1.18**: Update `search()` method to return `list[WebpageSnippet]` without filtering
|
| 57 |
-
- **Task 1.1.19**: Remove `_filter_results()` method (or make it optional)
|
| 58 |
-
- **Task 1.1.20**: Add error handling with `SearchError` and `RateLimitError`
|
| 59 |
-
- **Task 1.1.21**: Add structlog logging
|
| 60 |
-
- **Task 1.1.22**: Add type hints
|
| 61 |
-
|
| 62 |
-
**File**: `src/tools/vendored/searchxng_client.py`
|
| 63 |
-
- **Task 1.1.23**: Vendor `SearchXNGClient` class from `folder/tools/web_search.py` (lines 199-271)
|
| 64 |
-
- **Task 1.1.24**: Remove dependency on `ResearchAgent` and `ResearchRunner`
|
| 65 |
-
- **Task 1.1.25**: Replace filter agent with simple relevance filtering or remove it
|
| 66 |
-
- **Task 1.1.26**: Add `__init__` that takes `host: str` parameter
|
| 67 |
-
- **Task 1.1.27**: Update `search()` method to return `list[WebpageSnippet]` without filtering
|
| 68 |
-
- **Task 1.1.28**: Remove `_filter_results()` method (or make it optional)
|
| 69 |
-
- **Task 1.1.29**: Add error handling with `SearchError` and `RateLimitError`
|
| 70 |
-
- **Task 1.1.30**: Add structlog logging
|
| 71 |
-
- **Task 1.1.31**: Add type hints
|
| 72 |
-
|
| 73 |
-
#### Activity 1.2: Create Rate Limiting for Web Search
|
| 74 |
-
**File**: `src/tools/rate_limiter.py`
|
| 75 |
-
- **Task 1.2.1**: Add `get_serper_limiter()` function (rate: "10/second" with API key)
|
| 76 |
-
- **Task 1.2.2**: Add `get_searchxng_limiter()` function (rate: "5/second")
|
| 77 |
-
- **Task 1.2.3**: Use `RateLimiterFactory.get()` pattern
|
| 78 |
-
|
| 79 |
-
---
|
| 80 |
-
|
| 81 |
-
### PROJECT 2: Create Protocol-Compliant SerperWebSearchTool
|
| 82 |
-
|
| 83 |
-
#### Activity 2.1: Implement SerperWebSearchTool Class
|
| 84 |
-
**File**: `src/tools/serper_web_search.py`
|
| 85 |
-
- **Task 2.1.1**: Create new file `src/tools/serper_web_search.py`
|
| 86 |
-
- **Task 2.1.2**: Add imports:
|
| 87 |
-
- `from src.tools.base import SearchTool`
|
| 88 |
-
- `from src.tools.vendored.serper_client import SerperClient`
|
| 89 |
-
- `from src.tools.vendored.web_search_core import scrape_urls, WebpageSnippet`
|
| 90 |
-
- `from src.tools.rate_limiter import get_serper_limiter`
|
| 91 |
-
- `from src.tools.query_utils import preprocess_query`
|
| 92 |
-
- `from src.utils.config import settings`
|
| 93 |
-
- `from src.utils.exceptions import SearchError, RateLimitError`
|
| 94 |
-
- `from src.utils.models import Citation, Evidence`
|
| 95 |
-
- `import structlog`
|
| 96 |
-
- `from tenacity import retry, stop_after_attempt, wait_exponential`
|
| 97 |
-
|
| 98 |
-
- **Task 2.1.3**: Create `SerperWebSearchTool` class
|
| 99 |
-
- **Task 2.1.4**: Add `__init__(self, api_key: str | None = None)` method
|
| 100 |
-
- Line 2.1.4.1: Get API key from parameter or `settings.serper_api_key`
|
| 101 |
-
- Line 2.1.4.2: Validate API key is not None, raise `ConfigurationError` if missing
|
| 102 |
-
- Line 2.1.4.3: Initialize `SerperClient(api_key=self.api_key)`
|
| 103 |
-
- Line 2.1.4.4: Get rate limiter: `self._limiter = get_serper_limiter(self.api_key)`
|
| 104 |
-
|
| 105 |
-
- **Task 2.1.5**: Add `@property def name(self) -> str:` returning `"serper"`
|
| 106 |
-
|
| 107 |
-
- **Task 2.1.6**: Add `async def _rate_limit(self) -> None:` method
|
| 108 |
-
- Line 2.1.6.1: Call `await self._limiter.acquire()`
|
| 109 |
-
|
| 110 |
-
- **Task 2.1.7**: Add `@retry(...)` decorator with exponential backoff
|
| 111 |
-
|
| 112 |
-
- **Task 2.1.8**: Add `async def search(self, query: str, max_results: int = 10) -> list[Evidence]:` method
|
| 113 |
-
- Line 2.1.8.1: Call `await self._rate_limit()`
|
| 114 |
-
- Line 2.1.8.2: Preprocess query: `clean_query = preprocess_query(query)`
|
| 115 |
-
- Line 2.1.8.3: Use `clean_query if clean_query else query`
|
| 116 |
-
- Line 2.1.8.4: Call `search_results = await self._client.search(query, filter_for_relevance=False, max_results=max_results)`
|
| 117 |
-
- Line 2.1.8.5: Call `scraped = await scrape_urls(search_results)`
|
| 118 |
-
- Line 2.1.8.6: Convert `ScrapeResult` to `Evidence` objects:
|
| 119 |
-
- Line 2.1.8.6.1: Create `Citation` with `title`, `url`, `source="serper"`, `date="Unknown"`, `authors=[]`
|
| 120 |
-
- Line 2.1.8.6.2: Create `Evidence` with `content=scraped.text`, `citation`, `relevance=0.0`
|
| 121 |
-
- Line 2.1.8.7: Return `list[Evidence]`
|
| 122 |
-
- Line 2.1.8.8: Add try/except for `httpx.HTTPStatusError`:
|
| 123 |
-
- Line 2.1.8.8.1: Check for 429 status, raise `RateLimitError`
|
| 124 |
-
- Line 2.1.8.8.2: Otherwise raise `SearchError`
|
| 125 |
-
- Line 2.1.8.9: Add try/except for `httpx.TimeoutException`, raise `SearchError`
|
| 126 |
-
- Line 2.1.8.10: Add generic exception handler, log and raise `SearchError`
|
| 127 |
-
|
| 128 |
-
#### Activity 2.2: Implement SearchXNGWebSearchTool Class
|
| 129 |
-
**File**: `src/tools/searchxng_web_search.py`
|
| 130 |
-
- **Task 2.2.1**: Create new file `src/tools/searchxng_web_search.py`
|
| 131 |
-
- **Task 2.2.2**: Add imports (similar to SerperWebSearchTool)
|
| 132 |
-
- **Task 2.2.3**: Create `SearchXNGWebSearchTool` class
|
| 133 |
-
- **Task 2.2.4**: Add `__init__(self, host: str | None = None)` method
|
| 134 |
-
- Line 2.2.4.1: Get host from parameter or `settings.searchxng_host`
|
| 135 |
-
- Line 2.2.4.2: Validate host is not None, raise `ConfigurationError` if missing
|
| 136 |
-
- Line 2.2.4.3: Initialize `SearchXNGClient(host=self.host)`
|
| 137 |
-
- Line 2.2.4.4: Get rate limiter: `self._limiter = get_searchxng_limiter()`
|
| 138 |
-
|
| 139 |
-
- **Task 2.2.5**: Add `@property def name(self) -> str:` returning `"searchxng"`
|
| 140 |
-
|
| 141 |
-
- **Task 2.2.6**: Add `async def _rate_limit(self) -> None:` method
|
| 142 |
-
|
| 143 |
-
- **Task 2.2.7**: Add `@retry(...)` decorator
|
| 144 |
-
|
| 145 |
-
- **Task 2.2.8**: Add `async def search(self, query: str, max_results: int = 10) -> list[Evidence]:` method
|
| 146 |
-
- Line 2.2.8.1-2.2.8.10: Similar structure to SerperWebSearchTool
|
| 147 |
-
|
| 148 |
-
---
|
| 149 |
-
|
| 150 |
-
### PROJECT 3: Fix Existing WebSearchTool Protocol Compliance
|
| 151 |
-
|
| 152 |
-
#### Activity 3.1: Update WebSearchTool Class
|
| 153 |
-
**File**: `src/tools/web_search.py`
|
| 154 |
-
- **Task 3.1.1**: Add `@property def name(self) -> str:` method returning `"duckduckgo"` (after line 17)
|
| 155 |
-
|
| 156 |
-
- **Task 3.1.2**: Change `search()` return type from `SearchResult` to `list[Evidence]` (line 19)
|
| 157 |
-
|
| 158 |
-
- **Task 3.1.3**: Update `search()` method body:
|
| 159 |
-
- Line 3.1.3.1: Keep existing search logic (lines 21-43)
|
| 160 |
-
- Line 3.1.3.2: Instead of returning `SearchResult`, return `evidence` list directly (line 44)
|
| 161 |
-
- Line 3.1.3.3: Update exception handler to return empty list `[]` instead of `SearchResult` (line 51)
|
| 162 |
-
|
| 163 |
-
- **Task 3.1.4**: Add imports if needed:
|
| 164 |
-
- Line 3.1.4.1: `from src.utils.exceptions import SearchError`
|
| 165 |
-
- Line 3.1.4.2: Update exception handling to raise `SearchError` instead of returning error `SearchResult`
|
| 166 |
-
|
| 167 |
-
- **Task 3.1.5**: Add query preprocessing:
|
| 168 |
-
- Line 3.1.5.1: Import `from src.tools.query_utils import preprocess_query`
|
| 169 |
-
- Line 3.1.5.2: Add `clean_query = preprocess_query(query)` before search
|
| 170 |
-
- Line 3.1.5.3: Use `clean_query if clean_query else query`
|
| 171 |
-
|
| 172 |
-
#### Activity 3.2: Update Retrieval Agent Caller
|
| 173 |
-
**File**: `src/agents/retrieval_agent.py`
|
| 174 |
-
- **Task 3.2.1**: Update `search_web()` function (line 31):
|
| 175 |
-
- Line 3.2.1.1: Change `results = await _web_search.search(query, max_results)`
|
| 176 |
-
- Line 3.2.1.2: Change to `evidence = await _web_search.search(query, max_results)`
|
| 177 |
-
- Line 3.2.1.3: Update check: `if not evidence:` instead of `if not results.evidence:`
|
| 178 |
-
- Line 3.2.1.4: Update state update: `new_count = state.add_evidence(evidence)` instead of `results.evidence`
|
| 179 |
-
- Line 3.2.1.5: Update logging: `results_found=len(evidence)` instead of `len(results.evidence)`
|
| 180 |
-
- Line 3.2.1.6: Update output formatting: `for i, r in enumerate(evidence[:max_results], 1):` instead of `results.evidence[:max_results]`
|
| 181 |
-
- Line 3.2.1.7: Update deduplication: `await state.embedding_service.deduplicate(evidence)` instead of `results.evidence`
|
| 182 |
-
- Line 3.2.1.8: Update output message: `Found {len(evidence)} web results` instead of `len(results.evidence)`
|
| 183 |
-
|
| 184 |
-
---
|
| 185 |
-
|
| 186 |
-
### PROJECT 4: Integrate Web Search into SearchHandler
|
| 187 |
-
|
| 188 |
-
#### Activity 4.1: Create Web Search Tool Factory
|
| 189 |
-
**File**: `src/tools/web_search_factory.py`
|
| 190 |
-
- **Task 4.1.1**: Create new file `src/tools/web_search_factory.py`
|
| 191 |
-
- **Task 4.1.2**: Add imports:
|
| 192 |
-
- `from src.tools.web_search import WebSearchTool`
|
| 193 |
-
- `from src.tools.serper_web_search import SerperWebSearchTool`
|
| 194 |
-
- `from src.tools.searchxng_web_search import SearchXNGWebSearchTool`
|
| 195 |
-
- `from src.utils.config import settings`
|
| 196 |
-
- `from src.utils.exceptions import ConfigurationError`
|
| 197 |
-
- `import structlog`
|
| 198 |
-
|
| 199 |
-
- **Task 4.1.3**: Add `logger = structlog.get_logger()`
|
| 200 |
-
|
| 201 |
-
- **Task 4.1.4**: Create `def create_web_search_tool() -> SearchTool | None:` function
|
| 202 |
-
- Line 4.1.4.1: Check `settings.web_search_provider`
|
| 203 |
-
- Line 4.1.4.2: If `"serper"`:
|
| 204 |
-
- Line 4.1.4.2.1: Check `settings.serper_api_key` or `settings.web_search_available()`
|
| 205 |
-
- Line 4.1.4.2.2: If available, return `SerperWebSearchTool()`
|
| 206 |
-
- Line 4.1.4.2.3: Else log warning and return `None`
|
| 207 |
-
- Line 4.1.4.3: If `"searchxng"`:
|
| 208 |
-
- Line 4.1.4.3.1: Check `settings.searchxng_host` or `settings.web_search_available()`
|
| 209 |
-
- Line 4.1.4.3.2: If available, return `SearchXNGWebSearchTool()`
|
| 210 |
-
- Line 4.1.4.3.3: Else log warning and return `None`
|
| 211 |
-
- Line 4.1.4.4: If `"duckduckgo"`:
|
| 212 |
-
- Line 4.1.4.4.1: Return `WebSearchTool()` (always available)
|
| 213 |
-
- Line 4.1.4.5: If `"brave"` or `"tavily"`:
|
| 214 |
-
- Line 4.1.4.5.1: Log warning "Not yet implemented"
|
| 215 |
-
- Line 4.1.4.5.2: Return `None`
|
| 216 |
-
- Line 4.1.4.6: Default: return `WebSearchTool()` (fallback to DuckDuckGo)
|
| 217 |
-
|
| 218 |
-
#### Activity 4.2: Update SearchHandler Initialization
|
| 219 |
-
**File**: `src/app.py`
|
| 220 |
-
- **Task 4.2.1**: Add import: `from src.tools.web_search_factory import create_web_search_tool`
|
| 221 |
-
|
| 222 |
-
- **Task 4.2.2**: Update `configure_orchestrator()` function (around line 73):
|
| 223 |
-
- Line 4.2.2.1: Before creating `SearchHandler`, call `web_search_tool = create_web_search_tool()`
|
| 224 |
-
- Line 4.2.2.2: Create tools list: `tools = [PubMedTool(), ClinicalTrialsTool(), EuropePMCTool()]`
|
| 225 |
-
- Line 4.2.2.3: If `web_search_tool is not None`:
|
| 226 |
-
- Line 4.2.2.3.1: Append `web_search_tool` to tools list
|
| 227 |
-
- Line 4.2.2.3.2: Log info: "Web search tool added to search handler"
|
| 228 |
-
- Line 4.2.2.4: Update `SearchHandler` initialization to use `tools` list
|
| 229 |
-
|
| 230 |
-
---
|
| 231 |
-
|
| 232 |
-
### PROJECT 5: Update Callers and Dependencies
|
| 233 |
-
|
| 234 |
-
#### Activity 5.1: Update web_search_adapter
|
| 235 |
-
**File**: `src/tools/web_search_adapter.py`
|
| 236 |
-
- **Task 5.1.1**: Update `web_search()` function to use new implementation:
|
| 237 |
-
- Line 5.1.1.1: Import `from src.tools.web_search_factory import create_web_search_tool`
|
| 238 |
-
- Line 5.1.1.2: Remove dependency on `folder.tools.web_search`
|
| 239 |
-
- Line 5.1.1.3: Get tool: `tool = create_web_search_tool()`
|
| 240 |
-
- Line 5.1.1.4: If `tool is None`, return error message
|
| 241 |
-
- Line 5.1.1.5: Call `evidence = await tool.search(query, max_results=5)`
|
| 242 |
-
- Line 5.1.1.6: Convert `Evidence` objects to formatted string:
|
| 243 |
-
- Line 5.1.1.6.1: Format each evidence with title, URL, content preview
|
| 244 |
-
- Line 5.1.1.7: Return formatted string
|
| 245 |
-
|
| 246 |
-
#### Activity 5.2: Update Tool Executor
|
| 247 |
-
**File**: `src/tools/tool_executor.py`
|
| 248 |
-
- **Task 5.2.1**: Verify `web_search_adapter.web_search()` usage (line 86) still works
|
| 249 |
-
- **Task 5.2.2**: No changes needed if adapter is updated correctly
|
| 250 |
-
|
| 251 |
-
#### Activity 5.3: Update Planner Agent
|
| 252 |
-
**File**: `src/orchestrator/planner_agent.py`
|
| 253 |
-
- **Task 5.3.1**: Verify `web_search_adapter.web_search()` usage (line 14) still works
|
| 254 |
-
- **Task 5.3.2**: No changes needed if adapter is updated correctly
|
| 255 |
-
|
| 256 |
-
#### Activity 5.4: Remove Legacy Dependencies
|
| 257 |
-
**File**: `src/tools/web_search_adapter.py`
|
| 258 |
-
- **Task 5.4.1**: Remove import of `folder.llm_config` and `folder.tools.web_search`
|
| 259 |
-
- **Task 5.4.2**: Update error messages to reflect new implementation
|
| 260 |
-
|
| 261 |
-
---
|
| 262 |
-
|
| 263 |
-
### PROJECT 6: Testing and Validation
|
| 264 |
-
|
| 265 |
-
#### Activity 6.1: Unit Tests for Vendored Components
|
| 266 |
-
**File**: `tests/unit/tools/test_vendored_web_search_core.py`
|
| 267 |
-
- **Task 6.1.1**: Test `scrape_urls()` function
|
| 268 |
-
- **Task 6.1.2**: Test `fetch_and_process_url()` function
|
| 269 |
-
- **Task 6.1.3**: Test `html_to_text()` function
|
| 270 |
-
- **Task 6.1.4**: Test `is_valid_url()` function
|
| 271 |
-
|
| 272 |
-
**File**: `tests/unit/tools/test_vendored_serper_client.py`
|
| 273 |
-
- **Task 6.1.5**: Mock SerperClient API calls
|
| 274 |
-
- **Task 6.1.6**: Test successful search
|
| 275 |
-
- **Task 6.1.7**: Test error handling
|
| 276 |
-
- **Task 6.1.8**: Test rate limiting
|
| 277 |
-
|
| 278 |
-
**File**: `tests/unit/tools/test_vendored_searchxng_client.py`
|
| 279 |
-
- **Task 6.1.9**: Mock SearchXNGClient API calls
|
| 280 |
-
- **Task 6.1.10**: Test successful search
|
| 281 |
-
- **Task 6.1.11**: Test error handling
|
| 282 |
-
- **Task 6.1.12**: Test rate limiting
|
| 283 |
-
|
| 284 |
-
#### Activity 6.2: Unit Tests for Web Search Tools
|
| 285 |
-
**File**: `tests/unit/tools/test_serper_web_search.py`
|
| 286 |
-
- **Task 6.2.1**: Test `SerperWebSearchTool.__init__()` with valid API key
|
| 287 |
-
- **Task 6.2.2**: Test `SerperWebSearchTool.__init__()` without API key (should raise)
|
| 288 |
-
- **Task 6.2.3**: Test `name` property returns `"serper"`
|
| 289 |
-
- **Task 6.2.4**: Test `search()` returns `list[Evidence]`
|
| 290 |
-
- **Task 6.2.5**: Test `search()` with mocked SerperClient
|
| 291 |
-
- **Task 6.2.6**: Test error handling (SearchError, RateLimitError)
|
| 292 |
-
- **Task 6.2.7**: Test query preprocessing
|
| 293 |
-
- **Task 6.2.8**: Test rate limiting
|
| 294 |
-
|
| 295 |
-
**File**: `tests/unit/tools/test_searchxng_web_search.py`
|
| 296 |
-
- **Task 6.2.9**: Similar tests for SearchXNGWebSearchTool
|
| 297 |
-
|
| 298 |
-
**File**: `tests/unit/tools/test_web_search.py`
|
| 299 |
-
- **Task 6.2.10**: Test `WebSearchTool.name` property returns `"duckduckgo"`
|
| 300 |
-
- **Task 6.2.11**: Test `WebSearchTool.search()` returns `list[Evidence]`
|
| 301 |
-
- **Task 6.2.12**: Test `WebSearchTool.search()` with mocked DDGS
|
| 302 |
-
- **Task 6.2.13**: Test error handling
|
| 303 |
-
- **Task 6.2.14**: Test query preprocessing
|
| 304 |
-
|
| 305 |
-
#### Activity 6.3: Integration Tests
|
| 306 |
-
**File**: `tests/integration/test_web_search_integration.py`
|
| 307 |
-
- **Task 6.3.1**: Test `SerperWebSearchTool` with real API (marked `@pytest.mark.integration`)
|
| 308 |
-
- **Task 6.3.2**: Test `SearchXNGWebSearchTool` with real API (marked `@pytest.mark.integration`)
|
| 309 |
-
- **Task 6.3.3**: Test `WebSearchTool` with real DuckDuckGo (marked `@pytest.mark.integration`)
|
| 310 |
-
- **Task 6.3.4**: Test `create_web_search_tool()` factory function
|
| 311 |
-
- **Task 6.3.5**: Test SearchHandler with web search tool
|
| 312 |
-
|
| 313 |
-
#### Activity 6.4: Update Existing Tests
|
| 314 |
-
**File**: `tests/unit/agents/test_retrieval_agent.py`
|
| 315 |
-
- **Task 6.4.1**: Update tests to expect `list[Evidence]` instead of `SearchResult`
|
| 316 |
-
- **Task 6.4.2**: Mock `WebSearchTool.search()` to return `list[Evidence]`
|
| 317 |
-
|
| 318 |
-
**File**: `tests/unit/tools/test_tool_executor.py`
|
| 319 |
-
- **Task 6.4.3**: Verify tests still pass with updated `web_search_adapter`
|
| 320 |
-
|
| 321 |
-
---
|
| 322 |
-
|
| 323 |
-
## Implementation Order
|
| 324 |
-
|
| 325 |
-
1. **PROJECT 1**: Vendor core components (foundation)
|
| 326 |
-
2. **PROJECT 3**: Fix existing WebSearchTool (quick win, unblocks retrieval agent)
|
| 327 |
-
3. **PROJECT 2**: Create SerperWebSearchTool (new functionality)
|
| 328 |
-
4. **PROJECT 4**: Integrate into SearchHandler (main integration)
|
| 329 |
-
5. **PROJECT 5**: Update callers (cleanup dependencies)
|
| 330 |
-
6. **PROJECT 6**: Testing (validation)
|
| 331 |
-
|
| 332 |
-
---
|
| 333 |
-
|
| 334 |
-
## Dependencies and Prerequisites
|
| 335 |
-
|
| 336 |
-
### External Dependencies
|
| 337 |
-
- `aiohttp` - Already in requirements
|
| 338 |
-
- `beautifulsoup4` - Already in requirements
|
| 339 |
-
- `duckduckgo-search` - Already in requirements
|
| 340 |
-
- `tenacity` - Already in requirements
|
| 341 |
-
- `structlog` - Already in requirements
|
| 342 |
-
|
| 343 |
-
### Internal Dependencies
|
| 344 |
-
- `src/tools/base.py` - SearchTool protocol
|
| 345 |
-
- `src/tools/rate_limiter.py` - Rate limiting utilities
|
| 346 |
-
- `src/tools/query_utils.py` - Query preprocessing
|
| 347 |
-
- `src/utils/config.py` - Settings and configuration
|
| 348 |
-
- `src/utils/exceptions.py` - Custom exceptions
|
| 349 |
-
- `src/utils/models.py` - Evidence, Citation models
|
| 350 |
-
|
| 351 |
-
### Configuration Requirements
|
| 352 |
-
- `SERPER_API_KEY` - For Serper provider
|
| 353 |
-
- `SEARCHXNG_HOST` - For SearchXNG provider
|
| 354 |
-
- `WEB_SEARCH_PROVIDER` - Environment variable (default: "duckduckgo")
|
| 355 |
-
|
| 356 |
-
---
|
| 357 |
-
|
| 358 |
-
## Risk Assessment
|
| 359 |
-
|
| 360 |
-
### High Risk
|
| 361 |
-
- **Breaking changes to retrieval_agent.py**: Must update carefully to handle `list[Evidence]` instead of `SearchResult`
|
| 362 |
-
- **Legacy folder dependencies**: Need to ensure all code is properly vendored
|
| 363 |
-
|
| 364 |
-
### Medium Risk
|
| 365 |
-
- **Rate limiting**: Serper API may have different limits than expected
|
| 366 |
-
- **Error handling**: Need to handle API failures gracefully
|
| 367 |
-
|
| 368 |
-
### Low Risk
|
| 369 |
-
- **Query preprocessing**: May need adjustment for web search vs PubMed
|
| 370 |
-
- **Testing**: Integration tests require API keys
|
| 371 |
-
|
| 372 |
-
---
|
| 373 |
-
|
| 374 |
-
## Success Criteria
|
| 375 |
-
|
| 376 |
-
1. ✅ `SerperWebSearchTool` implements `SearchTool` protocol correctly
|
| 377 |
-
2. ✅ `WebSearchTool` implements `SearchTool` protocol correctly
|
| 378 |
-
3. ✅ Both tools can be added to `SearchHandler`
|
| 379 |
-
4. ✅ `web_search_adapter` works with new implementation
|
| 380 |
-
5. ✅ `retrieval_agent` works with updated `WebSearchTool`
|
| 381 |
-
6. ✅ All unit tests pass
|
| 382 |
-
7. ✅ Integration tests pass (with API keys)
|
| 383 |
-
8. ✅ No dependencies on `folder/tools/web_search.py` in `src/` code
|
| 384 |
-
9. ✅ Configuration supports multiple providers
|
| 385 |
-
10. ✅ Error handling is robust
|
| 386 |
-
|
| 387 |
-
---
|
| 388 |
-
|
| 389 |
-
## Notes
|
| 390 |
-
|
| 391 |
-
- The vendored code should be self-contained and not depend on `folder/` modules
|
| 392 |
-
- Filter agent functionality from original code is removed (can be added later if needed)
|
| 393 |
-
- Rate limiting follows the same pattern as PubMed tool
|
| 394 |
-
- Query preprocessing may need web-specific adjustments (less aggressive than PubMed)
|
| 395 |
-
- Consider adding relevance scoring in the future
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WEB_SEARCH_TOOL_ASSESSMENT.md
DELETED
|
@@ -1,239 +0,0 @@
|
|
| 1 |
-
# Web Search Tool Assessment
|
| 2 |
-
|
| 3 |
-
## Executive Summary
|
| 4 |
-
|
| 5 |
-
The application has **two separate web search implementations** with different readiness levels:
|
| 6 |
-
|
| 7 |
-
1. **`WebSearchTool`** (`src/tools/web_search.py`) - **Partially Ready** ⚠️
|
| 8 |
-
- Functional but **NOT compliant** with `SearchTool` protocol
|
| 9 |
-
- **NOT integrated** into main search handler
|
| 10 |
-
- Only used in magentic orchestrator's retrieval agent
|
| 11 |
-
|
| 12 |
-
2. **`web_search_adapter`** (`src/tools/web_search_adapter.py`) - **Functional** ✅
|
| 13 |
-
- Used by tool executor for WebSearchAgent tasks
|
| 14 |
-
- Relies on legacy `folder/tools/web_search.py` implementation
|
| 15 |
-
|
| 16 |
-
## Detailed Analysis
|
| 17 |
-
|
| 18 |
-
### 1. WebSearchTool (`src/tools/web_search.py`)
|
| 19 |
-
|
| 20 |
-
#### Current Implementation
|
| 21 |
-
- **Location**: `src/tools/web_search.py`
|
| 22 |
-
- **Provider**: DuckDuckGo (no API key required)
|
| 23 |
-
- **Status**: ⚠️ **Partially Ready**
|
| 24 |
-
|
| 25 |
-
#### Issues Identified
|
| 26 |
-
|
| 27 |
-
**❌ Protocol Non-Compliance:**
|
| 28 |
-
```python
|
| 29 |
-
# Missing required 'name' property
|
| 30 |
-
class WebSearchTool:
|
| 31 |
-
# Should have: @property def name(self) -> str: return "web"
|
| 32 |
-
|
| 33 |
-
# Wrong return type - should return list[Evidence], not SearchResult
|
| 34 |
-
async def search(self, query: str, max_results: int = 10) -> SearchResult:
|
| 35 |
-
# Returns SearchResult instead of list[Evidence]
|
| 36 |
-
```
|
| 37 |
-
|
| 38 |
-
**Comparison with other tools:**
|
| 39 |
-
- `PubMedTool` has `@property def name(self) -> str: return "pubmed"`
|
| 40 |
-
- `PubMedTool.search()` returns `list[Evidence]`
|
| 41 |
-
- `WebSearchTool` returns `SearchResult` (contains `evidence` list inside)
|
| 42 |
-
|
| 43 |
-
**❌ Not Integrated:**
|
| 44 |
-
- **NOT** included in `SearchHandler` initialization in `src/app.py`:
|
| 45 |
-
```python
|
| 46 |
-
search_handler = SearchHandler(
|
| 47 |
-
tools=[PubMedTool(), ClinicalTrialsTool(), EuropePMCTool()],
|
| 48 |
-
# WebSearchTool() is missing!
|
| 49 |
-
)
|
| 50 |
-
```
|
| 51 |
-
|
| 52 |
-
**✅ Current Usage:**
|
| 53 |
-
- Used in `src/agents/retrieval_agent.py` (magentic orchestrator):
|
| 54 |
-
```python
|
| 55 |
-
from src.tools.web_search import WebSearchTool
|
| 56 |
-
_web_search = WebSearchTool()
|
| 57 |
-
```
|
| 58 |
-
|
| 59 |
-
#### Fix Required
|
| 60 |
-
To make `WebSearchTool` compliant and usable:
|
| 61 |
-
|
| 62 |
-
1. **Add `name` property:**
|
| 63 |
-
```python
|
| 64 |
-
@property
|
| 65 |
-
def name(self) -> str:
|
| 66 |
-
return "web"
|
| 67 |
-
```
|
| 68 |
-
|
| 69 |
-
2. **Fix return type:**
|
| 70 |
-
```python
|
| 71 |
-
async def search(self, query: str, max_results: int = 10) -> list[Evidence]:
|
| 72 |
-
# ... existing code ...
|
| 73 |
-
return evidence # Return list[Evidence] directly, not SearchResult
|
| 74 |
-
```
|
| 75 |
-
|
| 76 |
-
3. **Register in SearchHandler:**
|
| 77 |
-
```python
|
| 78 |
-
from src.tools.web_search import WebSearchTool
|
| 79 |
-
|
| 80 |
-
search_handler = SearchHandler(
|
| 81 |
-
tools=[
|
| 82 |
-
PubMedTool(),
|
| 83 |
-
ClinicalTrialsTool(),
|
| 84 |
-
EuropePMCTool(),
|
| 85 |
-
WebSearchTool() # Add this
|
| 86 |
-
],
|
| 87 |
-
)
|
| 88 |
-
```
|
| 89 |
-
|
| 90 |
-
---
|
| 91 |
-
|
| 92 |
-
### 2. web_search_adapter (`src/tools/web_search_adapter.py`)
|
| 93 |
-
|
| 94 |
-
#### Current Implementation
|
| 95 |
-
- **Location**: `src/tools/web_search_adapter.py`
|
| 96 |
-
- **Status**: ✅ **Functional**
|
| 97 |
-
- **Provider**: Uses legacy `folder/tools/web_search.py` (Serper/SearchXNG)
|
| 98 |
-
|
| 99 |
-
#### Usage
|
| 100 |
-
- Used by `src/tools/tool_executor.py` for `WebSearchAgent` tasks:
|
| 101 |
-
```python
|
| 102 |
-
if task.agent == "WebSearchAgent":
|
| 103 |
-
result_text = await web_search(task.query)
|
| 104 |
-
```
|
| 105 |
-
|
| 106 |
-
- Used by `src/orchestrator/planner_agent.py` for background context
|
| 107 |
-
|
| 108 |
-
#### Dependencies
|
| 109 |
-
- Requires `folder/tools/web_search.py` (legacy implementation)
|
| 110 |
-
- Supports Serper API (requires `SERPER_API_KEY`)
|
| 111 |
-
- Supports SearchXNG API (requires `SEARCHXNG_HOST`)
|
| 112 |
-
|
| 113 |
-
#### Limitations
|
| 114 |
-
- Returns formatted string (not `Evidence` objects)
|
| 115 |
-
- Not integrated with `SearchHandler` (different execution path)
|
| 116 |
-
- Depends on legacy folder structure
|
| 117 |
-
|
| 118 |
-
---
|
| 119 |
-
|
| 120 |
-
## Integration Status
|
| 121 |
-
|
| 122 |
-
### SearchHandler Integration
|
| 123 |
-
**Current State**: ❌ **NOT Integrated**
|
| 124 |
-
|
| 125 |
-
The main `SearchHandler` in `src/app.py` only includes:
|
| 126 |
-
- `PubMedTool()`
|
| 127 |
-
- `ClinicalTrialsTool()`
|
| 128 |
-
- `EuropePMCTool()`
|
| 129 |
-
|
| 130 |
-
**WebSearchTool is missing from the main search flow.**
|
| 131 |
-
|
| 132 |
-
### Tool Executor Integration
|
| 133 |
-
**Current State**: ✅ **Integrated**
|
| 134 |
-
|
| 135 |
-
`web_search_adapter` is used via `tool_executor.py`:
|
| 136 |
-
- Executes when `AgentTask.agent == "WebSearchAgent"`
|
| 137 |
-
- Used in iterative/deep research flows
|
| 138 |
-
- Returns formatted text (not Evidence objects)
|
| 139 |
-
|
| 140 |
-
### Magentic Orchestrator Integration
|
| 141 |
-
**Current State**: ✅ **Integrated**
|
| 142 |
-
|
| 143 |
-
`WebSearchTool` is used in `retrieval_agent.py`:
|
| 144 |
-
- Direct instantiation: `_web_search = WebSearchTool()`
|
| 145 |
-
- Used via `search_web()` function
|
| 146 |
-
- Updates workflow state with evidence
|
| 147 |
-
|
| 148 |
-
---
|
| 149 |
-
|
| 150 |
-
## Can It Be Used?
|
| 151 |
-
|
| 152 |
-
### WebSearchTool (`src/tools/web_search.py`)
|
| 153 |
-
**Status**: ⚠️ **Can be used, but with limitations**
|
| 154 |
-
|
| 155 |
-
**Can be used:**
|
| 156 |
-
- ✅ In magentic orchestrator (already working)
|
| 157 |
-
- ✅ As standalone tool (functional)
|
| 158 |
-
|
| 159 |
-
**Cannot be used:**
|
| 160 |
-
- ❌ In `SearchHandler` (protocol non-compliance)
|
| 161 |
-
- ❌ In parallel search flows (not registered)
|
| 162 |
-
|
| 163 |
-
**To make fully usable:**
|
| 164 |
-
1. Fix protocol compliance (add `name`, fix return type)
|
| 165 |
-
2. Register in `SearchHandler`
|
| 166 |
-
3. Test integration
|
| 167 |
-
|
| 168 |
-
### web_search_adapter
|
| 169 |
-
**Status**: ✅ **Can be used**
|
| 170 |
-
|
| 171 |
-
**Can be used:**
|
| 172 |
-
- ✅ Via `tool_executor` for WebSearchAgent tasks
|
| 173 |
-
- ✅ In planner agent for background context
|
| 174 |
-
- ✅ In iterative/deep research flows
|
| 175 |
-
|
| 176 |
-
**Limitations:**
|
| 177 |
-
- Returns string format (not Evidence objects)
|
| 178 |
-
- Requires legacy folder dependencies
|
| 179 |
-
- Different execution path than SearchHandler
|
| 180 |
-
|
| 181 |
-
---
|
| 182 |
-
|
| 183 |
-
## Recommendations
|
| 184 |
-
|
| 185 |
-
### Priority 1: Fix WebSearchTool Protocol Compliance
|
| 186 |
-
Make `WebSearchTool` fully compliant with `SearchTool` protocol:
|
| 187 |
-
|
| 188 |
-
1. Add `name` property
|
| 189 |
-
2. Change return type from `SearchResult` to `list[Evidence]`
|
| 190 |
-
3. Update all callers if needed
|
| 191 |
-
|
| 192 |
-
### Priority 2: Integrate into SearchHandler
|
| 193 |
-
Add `WebSearchTool` to main search flow:
|
| 194 |
-
|
| 195 |
-
```python
|
| 196 |
-
from src.tools.web_search import WebSearchTool
|
| 197 |
-
|
| 198 |
-
search_handler = SearchHandler(
|
| 199 |
-
tools=[
|
| 200 |
-
PubMedTool(),
|
| 201 |
-
ClinicalTrialsTool(),
|
| 202 |
-
EuropePMCTool(),
|
| 203 |
-
WebSearchTool() # Add web search
|
| 204 |
-
],
|
| 205 |
-
)
|
| 206 |
-
```
|
| 207 |
-
|
| 208 |
-
### Priority 3: Consolidate Implementations
|
| 209 |
-
Consider consolidating the two implementations:
|
| 210 |
-
- Keep `WebSearchTool` as the main implementation
|
| 211 |
-
- Deprecate or migrate `web_search_adapter` usage
|
| 212 |
-
- Remove dependency on `folder/tools/web_search.py`
|
| 213 |
-
|
| 214 |
-
### Priority 4: Testing
|
| 215 |
-
Add tests for:
|
| 216 |
-
- Protocol compliance
|
| 217 |
-
- SearchHandler integration
|
| 218 |
-
- Error handling
|
| 219 |
-
- Rate limiting (if needed)
|
| 220 |
-
|
| 221 |
-
---
|
| 222 |
-
|
| 223 |
-
## Summary Table
|
| 224 |
-
|
| 225 |
-
| Component | Status | Protocol Compliant | Integrated | Can Be Used |
|
| 226 |
-
|-----------|--------|-------------------|------------|-------------|
|
| 227 |
-
| `WebSearchTool` | ⚠️ Partial | ❌ No | ❌ No | ⚠️ Limited |
|
| 228 |
-
| `web_search_adapter` | ✅ Functional | N/A | ✅ Yes (tool_executor) | ✅ Yes |
|
| 229 |
-
|
| 230 |
-
---
|
| 231 |
-
|
| 232 |
-
## Conclusion
|
| 233 |
-
|
| 234 |
-
The web search functionality exists in two forms:
|
| 235 |
-
1. **`WebSearchTool`** is functional but needs protocol fixes to be fully integrated
|
| 236 |
-
2. **`web_search_adapter`** is working but uses a different execution path
|
| 237 |
-
|
| 238 |
-
**Recommendation**: Fix `WebSearchTool` protocol compliance and integrate it into `SearchHandler` for unified search capabilities across all orchestrators.
|
| 239 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dev/Makefile
DELETED
|
@@ -1,51 +0,0 @@
|
|
| 1 |
-
.PHONY: install test lint format typecheck check clean all cov cov-html
|
| 2 |
-
|
| 3 |
-
# Default target
|
| 4 |
-
all: check
|
| 5 |
-
|
| 6 |
-
install:
|
| 7 |
-
uv sync --all-extras
|
| 8 |
-
uv run pre-commit install
|
| 9 |
-
|
| 10 |
-
test:
|
| 11 |
-
uv run pytest tests/unit/ -v -m "not openai" -p no:logfire
|
| 12 |
-
|
| 13 |
-
test-hf:
|
| 14 |
-
uv run pytest tests/ -v -m "huggingface" -p no:logfire
|
| 15 |
-
|
| 16 |
-
test-all:
|
| 17 |
-
uv run pytest tests/ -v -p no:logfire
|
| 18 |
-
|
| 19 |
-
# Coverage aliases
|
| 20 |
-
cov: test-cov
|
| 21 |
-
test-cov:
|
| 22 |
-
uv run pytest --cov=src --cov-report=term-missing -m "not openai" -p no:logfire
|
| 23 |
-
|
| 24 |
-
cov-html:
|
| 25 |
-
uv run pytest --cov=src --cov-report=html -p no:logfire
|
| 26 |
-
@echo "Coverage report: open htmlcov/index.html"
|
| 27 |
-
|
| 28 |
-
lint:
|
| 29 |
-
uv run ruff check src tests
|
| 30 |
-
|
| 31 |
-
format:
|
| 32 |
-
uv run ruff format src tests
|
| 33 |
-
|
| 34 |
-
typecheck:
|
| 35 |
-
uv run mypy src
|
| 36 |
-
|
| 37 |
-
check: lint typecheck test-cov
|
| 38 |
-
@echo "All checks passed!"
|
| 39 |
-
|
| 40 |
-
docs-build:
|
| 41 |
-
uv run mkdocs build
|
| 42 |
-
|
| 43 |
-
docs-serve:
|
| 44 |
-
uv run mkdocs serve
|
| 45 |
-
|
| 46 |
-
docs-clean:
|
| 47 |
-
rm -rf site/
|
| 48 |
-
|
| 49 |
-
clean:
|
| 50 |
-
rm -rf .pytest_cache .mypy_cache .ruff_cache __pycache__ .coverage htmlcov
|
| 51 |
-
find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dev/__init__.py
CHANGED
|
@@ -2,3 +2,4 @@
|
|
| 2 |
|
| 3 |
|
| 4 |
|
|
|
|
|
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
+
|
docs/MKDOCS_IMPROVEMENTS_ASSESSMENT.md
ADDED
|
@@ -0,0 +1,642 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# MkDocs & Material UI Improvement Assessment
|
| 2 |
+
|
| 3 |
+
## Current Configuration Analysis
|
| 4 |
+
|
| 5 |
+
Your current `mkdocs.yml` already includes many excellent features:
|
| 6 |
+
- ✅ Material theme with light/dark mode toggle
|
| 7 |
+
- ✅ Navigation tabs, sections, expand, and top navigation
|
| 8 |
+
- ✅ Search with suggestions and highlighting
|
| 9 |
+
- ✅ Code annotation and copy buttons
|
| 10 |
+
- ✅ Mermaid diagram support
|
| 11 |
+
- ✅ Code include plugin
|
| 12 |
+
- ✅ Minification for performance
|
| 13 |
+
- ✅ Comprehensive markdown extensions
|
| 14 |
+
|
| 15 |
+
## Recommended Improvements
|
| 16 |
+
|
| 17 |
+
### 1. **Versioning & Multi-Version Documentation** ⭐ High Priority
|
| 18 |
+
|
| 19 |
+
If you plan to maintain multiple versions or branches:
|
| 20 |
+
|
| 21 |
+
```yaml
|
| 22 |
+
plugins:
|
| 23 |
+
- search
|
| 24 |
+
- mermaid2
|
| 25 |
+
- codeinclude
|
| 26 |
+
- minify:
|
| 27 |
+
minify_html: true
|
| 28 |
+
minify_js: true
|
| 29 |
+
minify_css: true
|
| 30 |
+
- git-revision-date-localized:
|
| 31 |
+
enable_creation_date: true
|
| 32 |
+
type: timeago
|
| 33 |
+
# Optional: For versioning
|
| 34 |
+
# - versioning:
|
| 35 |
+
# version: ['dev', 'main']
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
**Benefits**: Shows when pages were last updated, helps users understand document freshness.
|
| 39 |
+
|
| 40 |
+
### 2. **Git Integration & Revision Information** ⭐ High Priority
|
| 41 |
+
|
| 42 |
+
Add revision dates and authors to pages:
|
| 43 |
+
|
| 44 |
+
```yaml
|
| 45 |
+
plugins:
|
| 46 |
+
- git-revision-date-localized:
|
| 47 |
+
enable_creation_date: true
|
| 48 |
+
type: timeago
|
| 49 |
+
fallback_to_build_date: true
|
| 50 |
+
- git-committers:
|
| 51 |
+
repository: DeepCritical/GradioDemo
|
| 52 |
+
branch: dev
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
**Benefits**: Users see when content was last updated, builds trust in documentation freshness.
|
| 56 |
+
|
| 57 |
+
### 3. **Enhanced Navigation Features** ⭐ High Priority
|
| 58 |
+
|
| 59 |
+
Add breadcrumbs and improve navigation:
|
| 60 |
+
|
| 61 |
+
```yaml
|
| 62 |
+
theme:
|
| 63 |
+
features:
|
| 64 |
+
- navigation.tabs
|
| 65 |
+
- navigation.sections
|
| 66 |
+
- navigation.expand
|
| 67 |
+
- navigation.top
|
| 68 |
+
- navigation.indexes # Add index pages
|
| 69 |
+
- navigation.instant # Instant page loads
|
| 70 |
+
- navigation.tracking # Track scroll position
|
| 71 |
+
- navigation.smooth # Smooth scrolling
|
| 72 |
+
- search.suggest
|
| 73 |
+
- search.highlight
|
| 74 |
+
- content.code.annotate
|
| 75 |
+
- content.code.copy
|
| 76 |
+
- content.tabs.link # Link to specific tabs
|
| 77 |
+
- content.tooltips # Tooltips for abbreviations
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
**Benefits**: Better UX, easier navigation, professional feel.
|
| 81 |
+
|
| 82 |
+
### 4. **Content Tabs for Code Examples** ⭐ High Priority
|
| 83 |
+
|
| 84 |
+
Perfect for showing multiple code examples (Python, TypeScript, etc.):
|
| 85 |
+
|
| 86 |
+
```yaml
|
| 87 |
+
markdown_extensions:
|
| 88 |
+
- pymdownx.tabbed:
|
| 89 |
+
alternate_style: true
|
| 90 |
+
combine_header_slug: true # Add this
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
**Usage in docs**:
|
| 94 |
+
````markdown
|
| 95 |
+
=== "Python"
|
| 96 |
+
```python
|
| 97 |
+
def example():
|
| 98 |
+
pass
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
=== "TypeScript"
|
| 102 |
+
```typescript
|
| 103 |
+
function example() {}
|
| 104 |
+
```
|
| 105 |
+
````
|
| 106 |
+
|
| 107 |
+
**Benefits**: Clean way to show multiple implementations without cluttering pages.
|
| 108 |
+
|
| 109 |
+
### 5. **Enhanced Admonitions** ⭐ Medium Priority
|
| 110 |
+
|
| 111 |
+
Add more admonition types and better styling:
|
| 112 |
+
|
| 113 |
+
```yaml
|
| 114 |
+
markdown_extensions:
|
| 115 |
+
- admonition
|
| 116 |
+
- pymdownx.details
|
| 117 |
+
- pymdownx.superfences:
|
| 118 |
+
custom_fences:
|
| 119 |
+
- name: mermaid
|
| 120 |
+
class: mermaid
|
| 121 |
+
format: !!python/name:pymdownx.superfences.fence_code_format
|
| 122 |
+
# Add custom admonition fences
|
| 123 |
+
- name: danger
|
| 124 |
+
class: danger
|
| 125 |
+
format: !!python/name:pymdownx.superfences.fence_code_format
|
| 126 |
+
```
|
| 127 |
+
|
| 128 |
+
**Usage**:
|
| 129 |
+
```markdown
|
| 130 |
+
!!! danger "Important"
|
| 131 |
+
This is a critical warning.
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
**Benefits**: Better visual hierarchy for warnings, tips, and important information.
|
| 135 |
+
|
| 136 |
+
### 6. **Math Formula Support** ⭐ Medium Priority (if needed)
|
| 137 |
+
|
| 138 |
+
If your documentation includes mathematical formulas:
|
| 139 |
+
|
| 140 |
+
```yaml
|
| 141 |
+
markdown_extensions:
|
| 142 |
+
- pymdownx.arithmatex:
|
| 143 |
+
generic: true
|
| 144 |
+
- pymdownx.superfences:
|
| 145 |
+
custom_fences:
|
| 146 |
+
- name: math
|
| 147 |
+
class: arithmetic
|
| 148 |
+
format: !!python/name:pymdownx.superfences.fence_code_format
|
| 149 |
+
|
| 150 |
+
extra_javascript:
|
| 151 |
+
- javascripts/mathjax.js
|
| 152 |
+
- https://polyfill.io/v3/polyfill.min.js?features=es6
|
| 153 |
+
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
|
| 154 |
+
```
|
| 155 |
+
|
| 156 |
+
**Benefits**: Essential for scientific/technical documentation with formulas.
|
| 157 |
+
|
| 158 |
+
### 7. **Better Code Highlighting** ⭐ Medium Priority
|
| 159 |
+
|
| 160 |
+
Add more language support and better themes:
|
| 161 |
+
|
| 162 |
+
```yaml
|
| 163 |
+
markdown_extensions:
|
| 164 |
+
- pymdownx.highlight:
|
| 165 |
+
anchor_linenums: true
|
| 166 |
+
line_spans: __span
|
| 167 |
+
pygments_lang_class: true
|
| 168 |
+
use_pygments: true
|
| 169 |
+
noclasses: false # Use CSS classes instead of inline styles
|
| 170 |
+
```
|
| 171 |
+
|
| 172 |
+
**Benefits**: Better syntax highlighting, more language support.
|
| 173 |
+
|
| 174 |
+
### 8. **Social Links Enhancement** ⭐ Low Priority
|
| 175 |
+
|
| 176 |
+
Add more social platforms and better icons:
|
| 177 |
+
|
| 178 |
+
```yaml
|
| 179 |
+
extra:
|
| 180 |
+
social:
|
| 181 |
+
- icon: fontawesome/brands/github
|
| 182 |
+
link: https://github.com/DeepCritical/GradioDemo
|
| 183 |
+
name: GitHub
|
| 184 |
+
- icon: fontawesome/brands/twitter
|
| 185 |
+
link: https://twitter.com/yourhandle
|
| 186 |
+
name: Twitter
|
| 187 |
+
- icon: material/web
|
| 188 |
+
link: https://huggingface.co/spaces/DataQuests/DeepCritical
|
| 189 |
+
name: HuggingFace Space
|
| 190 |
+
- icon: fontawesome/brands/discord
|
| 191 |
+
link: https://discord.gg/yourserver
|
| 192 |
+
name: Discord
|
| 193 |
+
```
|
| 194 |
+
|
| 195 |
+
**Benefits**: Better community engagement, more ways to connect.
|
| 196 |
+
|
| 197 |
+
### 9. **Analytics Integration** ⭐ Medium Priority
|
| 198 |
+
|
| 199 |
+
Add privacy-respecting analytics:
|
| 200 |
+
|
| 201 |
+
```yaml
|
| 202 |
+
extra:
|
| 203 |
+
analytics:
|
| 204 |
+
provider: google
|
| 205 |
+
property: G-XXXXXXXXXX
|
| 206 |
+
# Or use privacy-focused alternative:
|
| 207 |
+
# analytics:
|
| 208 |
+
# provider: plausible
|
| 209 |
+
# domain: yourdomain.com
|
| 210 |
+
```
|
| 211 |
+
|
| 212 |
+
**Benefits**: Understand how users interact with your documentation.
|
| 213 |
+
|
| 214 |
+
### 10. **Custom CSS/JS for Branding** ⭐ Low Priority
|
| 215 |
+
|
| 216 |
+
Add custom styling:
|
| 217 |
+
|
| 218 |
+
```yaml
|
| 219 |
+
extra_css:
|
| 220 |
+
- stylesheets/extra.css
|
| 221 |
+
|
| 222 |
+
extra_javascript:
|
| 223 |
+
- javascripts/extra.js
|
| 224 |
+
```
|
| 225 |
+
|
| 226 |
+
**Benefits**: Customize appearance, add interactive features.
|
| 227 |
+
|
| 228 |
+
### 11. **Better Table of Contents** ⭐ Medium Priority
|
| 229 |
+
|
| 230 |
+
Enhance TOC with more options:
|
| 231 |
+
|
| 232 |
+
```yaml
|
| 233 |
+
markdown_extensions:
|
| 234 |
+
- toc:
|
| 235 |
+
permalink: true
|
| 236 |
+
permalink_title: "Anchor link to this section"
|
| 237 |
+
baselevel: 1
|
| 238 |
+
toc_depth: 3
|
| 239 |
+
slugify: !!python/object/apply:pymdownx.slugs.slugify
|
| 240 |
+
kwds:
|
| 241 |
+
case: lower
|
| 242 |
+
```
|
| 243 |
+
|
| 244 |
+
**Benefits**: Better navigation within long pages, SEO-friendly anchor links.
|
| 245 |
+
|
| 246 |
+
### 12. **Image Optimization** ⭐ Medium Priority
|
| 247 |
+
|
| 248 |
+
Add image handling plugin:
|
| 249 |
+
|
| 250 |
+
```yaml
|
| 251 |
+
plugins:
|
| 252 |
+
- search
|
| 253 |
+
- mermaid2
|
| 254 |
+
- codeinclude
|
| 255 |
+
- minify:
|
| 256 |
+
minify_html: true
|
| 257 |
+
minify_js: true
|
| 258 |
+
minify_css: true
|
| 259 |
+
- git-revision-date-localized:
|
| 260 |
+
enable_creation_date: true
|
| 261 |
+
type: timeago
|
| 262 |
+
# Optional: Image optimization
|
| 263 |
+
# - awesome-pages # For better page organization
|
| 264 |
+
```
|
| 265 |
+
|
| 266 |
+
**Benefits**: Faster page loads, better mobile experience.
|
| 267 |
+
|
| 268 |
+
### 13. **Keyboard Shortcuts** ⭐ Low Priority
|
| 269 |
+
|
| 270 |
+
Enable keyboard navigation:
|
| 271 |
+
|
| 272 |
+
```yaml
|
| 273 |
+
theme:
|
| 274 |
+
keyboard_shortcuts:
|
| 275 |
+
search: true
|
| 276 |
+
previous: true
|
| 277 |
+
next: true
|
| 278 |
+
```
|
| 279 |
+
|
| 280 |
+
**Benefits**: Power users can navigate faster.
|
| 281 |
+
|
| 282 |
+
### 14. **Print Styles** ⭐ Low Priority
|
| 283 |
+
|
| 284 |
+
Better printing experience:
|
| 285 |
+
|
| 286 |
+
```yaml
|
| 287 |
+
theme:
|
| 288 |
+
features:
|
| 289 |
+
- navigation.tabs
|
| 290 |
+
- navigation.sections
|
| 291 |
+
- navigation.expand
|
| 292 |
+
- navigation.top
|
| 293 |
+
- navigation.indexes
|
| 294 |
+
- navigation.instant
|
| 295 |
+
- navigation.tracking
|
| 296 |
+
- navigation.smooth
|
| 297 |
+
- search.suggest
|
| 298 |
+
- search.highlight
|
| 299 |
+
- content.code.annotate
|
| 300 |
+
- content.code.copy
|
| 301 |
+
- content.tabs.link
|
| 302 |
+
- content.tooltips
|
| 303 |
+
- content.action.edit # Edit button
|
| 304 |
+
- content.action.view # View source
|
| 305 |
+
```
|
| 306 |
+
|
| 307 |
+
**Benefits**: Users can print documentation cleanly.
|
| 308 |
+
|
| 309 |
+
### 15. **Better Search Configuration** ⭐ Medium Priority
|
| 310 |
+
|
| 311 |
+
Enhance search capabilities:
|
| 312 |
+
|
| 313 |
+
```yaml
|
| 314 |
+
plugins:
|
| 315 |
+
- search:
|
| 316 |
+
lang:
|
| 317 |
+
- en
|
| 318 |
+
separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|&'
|
| 319 |
+
prebuild_index: true # For faster search
|
| 320 |
+
indexing: full # Full-text indexing
|
| 321 |
+
```
|
| 322 |
+
|
| 323 |
+
**Benefits**: Faster, more accurate search results.
|
| 324 |
+
|
| 325 |
+
### 16. **API Documentation Enhancements** ⭐ High Priority (for your API docs)
|
| 326 |
+
|
| 327 |
+
Since you have extensive API documentation, consider:
|
| 328 |
+
|
| 329 |
+
```yaml
|
| 330 |
+
markdown_extensions:
|
| 331 |
+
- pymdownx.superfences:
|
| 332 |
+
custom_fences:
|
| 333 |
+
- name: mermaid
|
| 334 |
+
class: mermaid
|
| 335 |
+
format: !!python/name:pymdownx.superfences.fence_code_format
|
| 336 |
+
preserve_tabs: true
|
| 337 |
+
# Add API-specific features
|
| 338 |
+
- attr_list
|
| 339 |
+
- md_in_html
|
| 340 |
+
- pymdownx.caret
|
| 341 |
+
- pymdownx.tilde
|
| 342 |
+
```
|
| 343 |
+
|
| 344 |
+
**Benefits**: Better formatting for API endpoints, parameters, responses.
|
| 345 |
+
|
| 346 |
+
### 17. **Blog/News Section** ⭐ Low Priority (if needed)
|
| 347 |
+
|
| 348 |
+
If you want to add a blog:
|
| 349 |
+
|
| 350 |
+
```yaml
|
| 351 |
+
plugins:
|
| 352 |
+
- blog:
|
| 353 |
+
blog_dir: blog
|
| 354 |
+
blog_description: "News and updates"
|
| 355 |
+
post_date_format: full
|
| 356 |
+
post_url_format: '{slug}'
|
| 357 |
+
archive: true
|
| 358 |
+
```
|
| 359 |
+
|
| 360 |
+
**Benefits**: Keep users updated with changelog, announcements.
|
| 361 |
+
|
| 362 |
+
### 18. **Tags and Categories** ⭐ Low Priority
|
| 363 |
+
|
| 364 |
+
Organize content with tags:
|
| 365 |
+
|
| 366 |
+
```yaml
|
| 367 |
+
markdown_extensions:
|
| 368 |
+
- meta
|
| 369 |
+
```
|
| 370 |
+
|
| 371 |
+
Then in frontmatter:
|
| 372 |
+
```markdown
|
| 373 |
+
---
|
| 374 |
+
tags:
|
| 375 |
+
- api
|
| 376 |
+
- agents
|
| 377 |
+
- getting-started
|
| 378 |
+
---
|
| 379 |
+
```
|
| 380 |
+
|
| 381 |
+
**Benefits**: Better content organization, related content discovery.
|
| 382 |
+
|
| 383 |
+
### 19. **Better Mobile Experience** ⭐ High Priority
|
| 384 |
+
|
| 385 |
+
Ensure mobile optimization:
|
| 386 |
+
|
| 387 |
+
```yaml
|
| 388 |
+
theme:
|
| 389 |
+
features:
|
| 390 |
+
- navigation.tabs
|
| 391 |
+
- navigation.sections
|
| 392 |
+
- navigation.expand
|
| 393 |
+
- navigation.top
|
| 394 |
+
- navigation.instant # Helps on mobile
|
| 395 |
+
- navigation.tracking
|
| 396 |
+
- navigation.smooth
|
| 397 |
+
- search.suggest
|
| 398 |
+
- search.highlight
|
| 399 |
+
- content.code.annotate
|
| 400 |
+
- content.code.copy
|
| 401 |
+
- content.tabs.link
|
| 402 |
+
- content.tooltips
|
| 403 |
+
- toc.integrate # Better mobile TOC
|
| 404 |
+
```
|
| 405 |
+
|
| 406 |
+
**Benefits**: Better experience for mobile users (growing segment).
|
| 407 |
+
|
| 408 |
+
### 20. **Feedback Mechanism** ⭐ Medium Priority
|
| 409 |
+
|
| 410 |
+
Add feedback buttons:
|
| 411 |
+
|
| 412 |
+
```yaml
|
| 413 |
+
extra:
|
| 414 |
+
feedback:
|
| 415 |
+
title: "Was this page helpful?"
|
| 416 |
+
ratings:
|
| 417 |
+
- icon: material/thumb-up-outline
|
| 418 |
+
name: "This page was helpful"
|
| 419 |
+
- icon: material/thumb-down-outline
|
| 420 |
+
name: "This page could be improved"
|
| 421 |
+
```
|
| 422 |
+
|
| 423 |
+
**Benefits**: Understand what content needs improvement.
|
| 424 |
+
|
| 425 |
+
## Priority Recommendations
|
| 426 |
+
|
| 427 |
+
### Immediate (High Impact, Easy Implementation)
|
| 428 |
+
1. ✅ **Git revision dates** - Shows content freshness
|
| 429 |
+
2. ✅ **Enhanced navigation features** - Better UX
|
| 430 |
+
3. ✅ **Content tabs** - Perfect for code examples
|
| 431 |
+
4. ✅ **Better search configuration** - Faster search
|
| 432 |
+
|
| 433 |
+
### Short-term (High Impact, Medium Effort)
|
| 434 |
+
5. ✅ **API documentation enhancements** - Better API docs
|
| 435 |
+
6. ✅ **Enhanced admonitions** - Better visual hierarchy
|
| 436 |
+
7. ✅ **Mobile optimization** - Better mobile experience
|
| 437 |
+
8. ✅ **Analytics** - Understand user behavior
|
| 438 |
+
|
| 439 |
+
### Long-term (Nice to Have)
|
| 440 |
+
9. ⚠️ **Versioning** - If you need multiple versions
|
| 441 |
+
10. ⚠️ **Math formulas** - If you have mathematical content
|
| 442 |
+
11. ⚠️ **Blog section** - If you want to publish updates
|
| 443 |
+
12. ⚠️ **Custom CSS/JS** - For advanced customization
|
| 444 |
+
|
| 445 |
+
## Implementation Example
|
| 446 |
+
|
| 447 |
+
Here's an enhanced `mkdocs.yml` with the high-priority improvements:
|
| 448 |
+
|
| 449 |
+
```yaml
|
| 450 |
+
site_name: The DETERMINATOR
|
| 451 |
+
site_description: Generalist Deep Research Agent that Stops at Nothing
|
| 452 |
+
site_author: The DETERMINATOR Team
|
| 453 |
+
site_url: https://deepcritical.github.io/GradioDemo/
|
| 454 |
+
|
| 455 |
+
repo_name: DeepCritical/GradioDemo
|
| 456 |
+
repo_url: https://github.com/DeepCritical/GradioDemo
|
| 457 |
+
edit_uri: edit/dev/docs/
|
| 458 |
+
|
| 459 |
+
strict: false
|
| 460 |
+
|
| 461 |
+
theme:
|
| 462 |
+
name: material
|
| 463 |
+
palette:
|
| 464 |
+
- scheme: default
|
| 465 |
+
primary: orange
|
| 466 |
+
accent: red
|
| 467 |
+
toggle:
|
| 468 |
+
icon: material/brightness-7
|
| 469 |
+
name: Switch to dark mode
|
| 470 |
+
- scheme: slate
|
| 471 |
+
primary: orange
|
| 472 |
+
accent: red
|
| 473 |
+
toggle:
|
| 474 |
+
icon: material/brightness-4
|
| 475 |
+
name: Switch to light mode
|
| 476 |
+
features:
|
| 477 |
+
- navigation.tabs
|
| 478 |
+
- navigation.sections
|
| 479 |
+
- navigation.expand
|
| 480 |
+
- navigation.top
|
| 481 |
+
- navigation.indexes
|
| 482 |
+
- navigation.instant
|
| 483 |
+
- navigation.tracking
|
| 484 |
+
- navigation.smooth
|
| 485 |
+
- search.suggest
|
| 486 |
+
- search.highlight
|
| 487 |
+
- content.code.annotate
|
| 488 |
+
- content.code.copy
|
| 489 |
+
- content.tabs.link
|
| 490 |
+
- content.tooltips
|
| 491 |
+
- toc.integrate
|
| 492 |
+
icon:
|
| 493 |
+
repo: fontawesome/brands/github
|
| 494 |
+
language: en
|
| 495 |
+
|
| 496 |
+
plugins:
|
| 497 |
+
- search:
|
| 498 |
+
lang:
|
| 499 |
+
- en
|
| 500 |
+
separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|&'
|
| 501 |
+
prebuild_index: true
|
| 502 |
+
indexing: full
|
| 503 |
+
- mermaid2
|
| 504 |
+
- codeinclude
|
| 505 |
+
- git-revision-date-localized:
|
| 506 |
+
enable_creation_date: true
|
| 507 |
+
type: timeago
|
| 508 |
+
fallback_to_build_date: true
|
| 509 |
+
- minify:
|
| 510 |
+
minify_html: true
|
| 511 |
+
minify_js: true
|
| 512 |
+
minify_css: true
|
| 513 |
+
|
| 514 |
+
markdown_extensions:
|
| 515 |
+
- dev.docs_plugins:
|
| 516 |
+
base_path: "."
|
| 517 |
+
- pymdownx.highlight:
|
| 518 |
+
anchor_linenums: true
|
| 519 |
+
line_spans: __span
|
| 520 |
+
pygments_lang_class: true
|
| 521 |
+
use_pygments: true
|
| 522 |
+
noclasses: false
|
| 523 |
+
- pymdownx.inlinehilite
|
| 524 |
+
- pymdownx.superfences:
|
| 525 |
+
custom_fences:
|
| 526 |
+
- name: mermaid
|
| 527 |
+
class: mermaid
|
| 528 |
+
format: !!python/name:pymdownx.superfences.fence_code_format
|
| 529 |
+
preserve_tabs: true
|
| 530 |
+
- pymdownx.tabbed:
|
| 531 |
+
alternate_style: true
|
| 532 |
+
combine_header_slug: true
|
| 533 |
+
- pymdownx.tasklist:
|
| 534 |
+
custom_checkbox: true
|
| 535 |
+
- pymdownx.emoji:
|
| 536 |
+
emoji_generator: !!python/name:pymdownx.emoji.to_svg
|
| 537 |
+
emoji_index: !!python/name:pymdownx.emoji.twemoji
|
| 538 |
+
- pymdownx.snippets
|
| 539 |
+
- admonition
|
| 540 |
+
- pymdownx.details
|
| 541 |
+
- attr_list
|
| 542 |
+
- md_in_html
|
| 543 |
+
- tables
|
| 544 |
+
- meta
|
| 545 |
+
- toc:
|
| 546 |
+
permalink: true
|
| 547 |
+
permalink_title: "Anchor link to this section"
|
| 548 |
+
baselevel: 1
|
| 549 |
+
toc_depth: 3
|
| 550 |
+
slugify: !!python/object/apply:pymdownx.slugs.slugify
|
| 551 |
+
kwds:
|
| 552 |
+
case: lower
|
| 553 |
+
|
| 554 |
+
nav:
|
| 555 |
+
- Home: index.md
|
| 556 |
+
- Overview:
|
| 557 |
+
- overview/architecture.md
|
| 558 |
+
- overview/features.md
|
| 559 |
+
- Getting Started:
|
| 560 |
+
- getting-started/installation.md
|
| 561 |
+
- getting-started/quick-start.md
|
| 562 |
+
- getting-started/mcp-integration.md
|
| 563 |
+
- getting-started/examples.md
|
| 564 |
+
- Configuration:
|
| 565 |
+
- configuration/index.md
|
| 566 |
+
- Architecture:
|
| 567 |
+
- "Graph Orchestration": architecture/graph_orchestration.md
|
| 568 |
+
- "Workflow Diagrams": architecture/workflow-diagrams.md
|
| 569 |
+
- "Agents": architecture/agents.md
|
| 570 |
+
- "Orchestrators": architecture/orchestrators.md
|
| 571 |
+
- "Tools": architecture/tools.md
|
| 572 |
+
- "Middleware": architecture/middleware.md
|
| 573 |
+
- "Services": architecture/services.md
|
| 574 |
+
- API Reference:
|
| 575 |
+
- api/agents.md
|
| 576 |
+
- api/tools.md
|
| 577 |
+
- api/orchestrators.md
|
| 578 |
+
- api/services.md
|
| 579 |
+
- api/models.md
|
| 580 |
+
- Contributing:
|
| 581 |
+
- contributing/index.md
|
| 582 |
+
- contributing/code-quality.md
|
| 583 |
+
- contributing/code-style.md
|
| 584 |
+
- contributing/error-handling.md
|
| 585 |
+
- contributing/implementation-patterns.md
|
| 586 |
+
- contributing/prompt-engineering.md
|
| 587 |
+
- contributing/testing.md
|
| 588 |
+
- License: LICENSE.md
|
| 589 |
+
- Team: team.md
|
| 590 |
+
|
| 591 |
+
extra:
|
| 592 |
+
social:
|
| 593 |
+
- icon: fontawesome/brands/github
|
| 594 |
+
link: https://github.com/DeepCritical/GradioDemo
|
| 595 |
+
name: GitHub
|
| 596 |
+
- icon: material/web
|
| 597 |
+
link: https://huggingface.co/spaces/DataQuests/DeepCritical
|
| 598 |
+
name: HuggingFace Space
|
| 599 |
+
version:
|
| 600 |
+
provider: mike
|
| 601 |
+
generator:
|
| 602 |
+
enabled: false
|
| 603 |
+
|
| 604 |
+
copyright: Copyright © 2024 DeepCritical Team
|
| 605 |
+
```
|
| 606 |
+
|
| 607 |
+
## Additional Documentation Improvements
|
| 608 |
+
|
| 609 |
+
### Content Structure
|
| 610 |
+
1. **Add a changelog page** - Keep users informed of updates
|
| 611 |
+
2. **Add a FAQ section** - Address common questions
|
| 612 |
+
3. **Add a glossary** - Define technical terms
|
| 613 |
+
4. **Add a troubleshooting guide** - Help users solve common issues
|
| 614 |
+
5. **Add video tutorials** - Embed videos for complex topics
|
| 615 |
+
|
| 616 |
+
### Visual Enhancements
|
| 617 |
+
1. **Add diagrams** - Use more Mermaid diagrams for complex flows
|
| 618 |
+
2. **Add screenshots** - Visual guides for UI features
|
| 619 |
+
3. **Add code examples** - More practical examples
|
| 620 |
+
4. **Add comparison tables** - Compare different approaches/options
|
| 621 |
+
|
| 622 |
+
### SEO & Discoverability
|
| 623 |
+
1. **Add meta descriptions** - Better search engine results
|
| 624 |
+
2. **Add Open Graph tags** - Better social media sharing
|
| 625 |
+
3. **Add sitemap** - Help search engines index your docs
|
| 626 |
+
4. **Add robots.txt** - Control search engine crawling
|
| 627 |
+
|
| 628 |
+
## Next Steps
|
| 629 |
+
|
| 630 |
+
1. Review this assessment
|
| 631 |
+
2. Prioritize features based on your needs
|
| 632 |
+
3. Test changes in a branch
|
| 633 |
+
4. Gather user feedback
|
| 634 |
+
5. Iterate and improve
|
| 635 |
+
|
| 636 |
+
## Resources
|
| 637 |
+
|
| 638 |
+
- [MkDocs User Guide](https://www.mkdocs.org/user-guide/)
|
| 639 |
+
- [Material for MkDocs Documentation](https://squidfunk.github.io/mkdocs-material/)
|
| 640 |
+
- [Material for MkDocs Reference](https://squidfunk.github.io/mkdocs-material/reference/)
|
| 641 |
+
- [MkDocs Plugins](https://github.com/mkdocs/mkdocs/wiki/MkDocs-Plugins)
|
| 642 |
+
|
docs/api/agents.md
CHANGED
|
@@ -12,27 +12,19 @@ This page documents the API for DeepCritical agents.
|
|
| 12 |
|
| 13 |
#### `evaluate`
|
| 14 |
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
query: str,
|
| 19 |
-
background_context: str,
|
| 20 |
-
conversation_history: Conversation,
|
| 21 |
-
iteration: int,
|
| 22 |
-
time_elapsed_minutes: float,
|
| 23 |
-
max_time_minutes: float
|
| 24 |
-
) -> KnowledgeGapOutput
|
| 25 |
-
```
|
| 26 |
|
| 27 |
Evaluates research completeness and identifies outstanding knowledge gaps.
|
| 28 |
|
| 29 |
**Parameters**:
|
| 30 |
- `query`: Research query string
|
| 31 |
-
- `background_context`: Background context for the query
|
| 32 |
-
- `conversation_history`:
|
| 33 |
-
- `iteration`: Current iteration number
|
| 34 |
-
- `time_elapsed_minutes`: Elapsed time in minutes
|
| 35 |
-
- `max_time_minutes`: Maximum time limit in minutes
|
| 36 |
|
| 37 |
**Returns**: `KnowledgeGapOutput` with:
|
| 38 |
- `research_complete`: Boolean indicating if research is complete
|
|
@@ -48,21 +40,17 @@ Evaluates research completeness and identifies outstanding knowledge gaps.
|
|
| 48 |
|
| 49 |
#### `select_tools`
|
| 50 |
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
query: str,
|
| 55 |
-
knowledge_gaps: list[str],
|
| 56 |
-
available_tools: list[str]
|
| 57 |
-
) -> AgentSelectionPlan
|
| 58 |
-
```
|
| 59 |
|
| 60 |
-
Selects tools for addressing knowledge
|
| 61 |
|
| 62 |
**Parameters**:
|
|
|
|
| 63 |
- `query`: Research query string
|
| 64 |
-
- `
|
| 65 |
-
- `
|
| 66 |
|
| 67 |
**Returns**: `AgentSelectionPlan` with list of `AgentTask` objects.
|
| 68 |
|
|
@@ -76,23 +64,17 @@ Selects tools for addressing knowledge gaps.
|
|
| 76 |
|
| 77 |
#### `write_report`
|
| 78 |
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
query: str,
|
| 83 |
-
findings: str,
|
| 84 |
-
output_length: str = "medium",
|
| 85 |
-
output_instructions: str | None = None
|
| 86 |
-
) -> str
|
| 87 |
-
```
|
| 88 |
|
| 89 |
Generates a markdown report from research findings.
|
| 90 |
|
| 91 |
**Parameters**:
|
| 92 |
- `query`: Research query string
|
| 93 |
- `findings`: Research findings to include in report
|
| 94 |
-
- `output_length`:
|
| 95 |
-
- `output_instructions`:
|
| 96 |
|
| 97 |
**Returns**: Markdown string with numbered citations.
|
| 98 |
|
|
@@ -106,36 +88,25 @@ Generates a markdown report from research findings.
|
|
| 106 |
|
| 107 |
#### `write_next_section`
|
| 108 |
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
query: str,
|
| 113 |
-
draft: ReportDraft,
|
| 114 |
-
section_title: str,
|
| 115 |
-
section_content: str
|
| 116 |
-
) -> LongWriterOutput
|
| 117 |
-
```
|
| 118 |
|
| 119 |
Writes the next section of a long-form report.
|
| 120 |
|
| 121 |
**Parameters**:
|
| 122 |
-
- `
|
| 123 |
-
- `
|
| 124 |
-
- `
|
| 125 |
-
- `
|
| 126 |
|
| 127 |
-
**Returns**: `LongWriterOutput` with
|
| 128 |
|
| 129 |
#### `write_report`
|
| 130 |
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
query: str,
|
| 135 |
-
report_title: str,
|
| 136 |
-
report_draft: ReportDraft
|
| 137 |
-
) -> str
|
| 138 |
-
```
|
| 139 |
|
| 140 |
Generates final report from draft.
|
| 141 |
|
|
@@ -156,14 +127,9 @@ Generates final report from draft.
|
|
| 156 |
|
| 157 |
#### `proofread`
|
| 158 |
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
query: str,
|
| 163 |
-
report_title: str,
|
| 164 |
-
report_draft: ReportDraft
|
| 165 |
-
) -> str
|
| 166 |
-
```
|
| 167 |
|
| 168 |
Proofreads and polishes a report draft.
|
| 169 |
|
|
@@ -184,21 +150,17 @@ Proofreads and polishes a report draft.
|
|
| 184 |
|
| 185 |
#### `generate_observations`
|
| 186 |
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
query: str,
|
| 191 |
-
background_context: str,
|
| 192 |
-
conversation_history: Conversation
|
| 193 |
-
) -> str
|
| 194 |
-
```
|
| 195 |
|
| 196 |
Generates observations from conversation history.
|
| 197 |
|
| 198 |
**Parameters**:
|
| 199 |
- `query`: Research query string
|
| 200 |
-
- `background_context`:
|
| 201 |
-
- `conversation_history`:
|
|
|
|
| 202 |
|
| 203 |
**Returns**: Observation string.
|
| 204 |
|
|
@@ -210,14 +172,11 @@ Generates observations from conversation history.
|
|
| 210 |
|
| 211 |
### Methods
|
| 212 |
|
| 213 |
-
#### `
|
| 214 |
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
query: str
|
| 219 |
-
) -> ParsedQuery
|
| 220 |
-
```
|
| 221 |
|
| 222 |
Parses and improves a user query.
|
| 223 |
|
|
@@ -241,6 +200,7 @@ All agents have factory functions in `src.agent_factory.agents`:
|
|
| 241 |
|
| 242 |
**Parameters**:
|
| 243 |
- `model`: Optional Pydantic AI model. If None, uses `get_model()` from settings.
|
|
|
|
| 244 |
|
| 245 |
**Returns**: Agent instance.
|
| 246 |
|
|
|
|
| 12 |
|
| 13 |
#### `evaluate`
|
| 14 |
|
| 15 |
+
<!--codeinclude-->
|
| 16 |
+
[KnowledgeGapAgent.evaluate](../src/agents/knowledge_gap.py) start_line:66 end_line:74
|
| 17 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
Evaluates research completeness and identifies outstanding knowledge gaps.
|
| 20 |
|
| 21 |
**Parameters**:
|
| 22 |
- `query`: Research query string
|
| 23 |
+
- `background_context`: Background context for the query (default: "")
|
| 24 |
+
- `conversation_history`: History of actions, findings, and thoughts as string (default: "")
|
| 25 |
+
- `iteration`: Current iteration number (default: 0)
|
| 26 |
+
- `time_elapsed_minutes`: Elapsed time in minutes (default: 0.0)
|
| 27 |
+
- `max_time_minutes`: Maximum time limit in minutes (default: 10)
|
| 28 |
|
| 29 |
**Returns**: `KnowledgeGapOutput` with:
|
| 30 |
- `research_complete`: Boolean indicating if research is complete
|
|
|
|
| 40 |
|
| 41 |
#### `select_tools`
|
| 42 |
|
| 43 |
+
<!--codeinclude-->
|
| 44 |
+
[ToolSelectorAgent.select_tools](../src/agents/tool_selector.py) start_line:78 end_line:84
|
| 45 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
+
Selects tools for addressing a knowledge gap.
|
| 48 |
|
| 49 |
**Parameters**:
|
| 50 |
+
- `gap`: The knowledge gap to address
|
| 51 |
- `query`: Research query string
|
| 52 |
+
- `background_context`: Optional background context (default: "")
|
| 53 |
+
- `conversation_history`: History of actions, findings, and thoughts as string (default: "")
|
| 54 |
|
| 55 |
**Returns**: `AgentSelectionPlan` with list of `AgentTask` objects.
|
| 56 |
|
|
|
|
| 64 |
|
| 65 |
#### `write_report`
|
| 66 |
|
| 67 |
+
<!--codeinclude-->
|
| 68 |
+
[WriterAgent.write_report](../src/agents/writer.py) start_line:67 end_line:73
|
| 69 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
|
| 71 |
Generates a markdown report from research findings.
|
| 72 |
|
| 73 |
**Parameters**:
|
| 74 |
- `query`: Research query string
|
| 75 |
- `findings`: Research findings to include in report
|
| 76 |
+
- `output_length`: Optional description of desired output length (default: "")
|
| 77 |
+
- `output_instructions`: Optional additional instructions for report generation (default: "")
|
| 78 |
|
| 79 |
**Returns**: Markdown string with numbered citations.
|
| 80 |
|
|
|
|
| 88 |
|
| 89 |
#### `write_next_section`
|
| 90 |
|
| 91 |
+
<!--codeinclude-->
|
| 92 |
+
[LongWriterAgent.write_next_section](../src/agents/long_writer.py) start_line:94 end_line:100
|
| 93 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
Writes the next section of a long-form report.
|
| 96 |
|
| 97 |
**Parameters**:
|
| 98 |
+
- `original_query`: The original research query
|
| 99 |
+
- `report_draft`: Current report draft as string (all sections written so far)
|
| 100 |
+
- `next_section_title`: Title of the section to write
|
| 101 |
+
- `next_section_draft`: Draft content for the next section
|
| 102 |
|
| 103 |
+
**Returns**: `LongWriterOutput` with formatted section and references.
|
| 104 |
|
| 105 |
#### `write_report`
|
| 106 |
|
| 107 |
+
<!--codeinclude-->
|
| 108 |
+
[LongWriterAgent.write_report](../src/agents/long_writer.py) start_line:263 end_line:268
|
| 109 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
Generates final report from draft.
|
| 112 |
|
|
|
|
| 127 |
|
| 128 |
#### `proofread`
|
| 129 |
|
| 130 |
+
<!--codeinclude-->
|
| 131 |
+
[ProofreaderAgent.proofread](../src/agents/proofreader.py) start_line:72 end_line:76
|
| 132 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
|
| 134 |
Proofreads and polishes a report draft.
|
| 135 |
|
|
|
|
| 150 |
|
| 151 |
#### `generate_observations`
|
| 152 |
|
| 153 |
+
<!--codeinclude-->
|
| 154 |
+
[ThinkingAgent.generate_observations](../src/agents/thinking.py) start_line:70 end_line:76
|
| 155 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
|
| 157 |
Generates observations from conversation history.
|
| 158 |
|
| 159 |
**Parameters**:
|
| 160 |
- `query`: Research query string
|
| 161 |
+
- `background_context`: Optional background context (default: "")
|
| 162 |
+
- `conversation_history`: History of actions, findings, and thoughts as string (default: "")
|
| 163 |
+
- `iteration`: Current iteration number (default: 1)
|
| 164 |
|
| 165 |
**Returns**: Observation string.
|
| 166 |
|
|
|
|
| 172 |
|
| 173 |
### Methods
|
| 174 |
|
| 175 |
+
#### `parse`
|
| 176 |
|
| 177 |
+
<!--codeinclude-->
|
| 178 |
+
[InputParserAgent.parse](../src/agents/input_parser.py) start_line:82 end_line:82
|
| 179 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
| 180 |
|
| 181 |
Parses and improves a user query.
|
| 182 |
|
|
|
|
| 200 |
|
| 201 |
**Parameters**:
|
| 202 |
- `model`: Optional Pydantic AI model. If None, uses `get_model()` from settings.
|
| 203 |
+
- `oauth_token`: Optional OAuth token from HuggingFace login (takes priority over env vars)
|
| 204 |
|
| 205 |
**Returns**: Agent instance.
|
| 206 |
|
docs/api/models.md
CHANGED
|
@@ -15,7 +15,7 @@ This page documents the Pydantic models used throughout DeepCritical.
|
|
| 15 |
**Fields**:
|
| 16 |
- `citation`: Citation information (title, URL, date, authors)
|
| 17 |
- `content`: Evidence text content
|
| 18 |
-
- `
|
| 19 |
- `metadata`: Additional metadata dictionary
|
| 20 |
|
| 21 |
## Citation
|
|
@@ -29,9 +29,10 @@ This page documents the Pydantic models used throughout DeepCritical.
|
|
| 29 |
<!--/codeinclude-->
|
| 30 |
|
| 31 |
**Fields**:
|
|
|
|
| 32 |
- `title`: Article/trial title
|
| 33 |
- `url`: Source URL
|
| 34 |
-
- `date`: Publication date (
|
| 35 |
- `authors`: List of authors (optional)
|
| 36 |
|
| 37 |
## KnowledgeGapOutput
|
|
@@ -72,9 +73,10 @@ This page documents the Pydantic models used throughout DeepCritical.
|
|
| 72 |
<!--/codeinclude-->
|
| 73 |
|
| 74 |
**Fields**:
|
| 75 |
-
- `
|
| 76 |
-
- `
|
| 77 |
-
- `
|
|
|
|
| 78 |
|
| 79 |
## ReportDraft
|
| 80 |
|
|
@@ -87,9 +89,7 @@ This page documents the Pydantic models used throughout DeepCritical.
|
|
| 87 |
<!--/codeinclude-->
|
| 88 |
|
| 89 |
**Fields**:
|
| 90 |
-
- `title`: Report title
|
| 91 |
- `sections`: List of report sections
|
| 92 |
-
- `references`: List of citations
|
| 93 |
|
| 94 |
## ReportSection
|
| 95 |
|
|
@@ -102,9 +102,8 @@ This page documents the Pydantic models used throughout DeepCritical.
|
|
| 102 |
<!--/codeinclude-->
|
| 103 |
|
| 104 |
**Fields**:
|
| 105 |
-
- `
|
| 106 |
-
- `
|
| 107 |
-
- `order`: Section order number
|
| 108 |
|
| 109 |
## ParsedQuery
|
| 110 |
|
|
@@ -134,7 +133,7 @@ This page documents the Pydantic models used throughout DeepCritical.
|
|
| 134 |
<!--/codeinclude-->
|
| 135 |
|
| 136 |
**Fields**:
|
| 137 |
-
- `
|
| 138 |
|
| 139 |
## IterationData
|
| 140 |
|
|
@@ -147,12 +146,10 @@ This page documents the Pydantic models used throughout DeepCritical.
|
|
| 147 |
<!--/codeinclude-->
|
| 148 |
|
| 149 |
**Fields**:
|
| 150 |
-
- `
|
| 151 |
-
- `
|
| 152 |
-
- `
|
| 153 |
-
- `
|
| 154 |
-
- `findings`: Findings from tools
|
| 155 |
-
- `thoughts`: Agent thoughts
|
| 156 |
|
| 157 |
## AgentEvent
|
| 158 |
|
|
@@ -180,12 +177,13 @@ This page documents the Pydantic models used throughout DeepCritical.
|
|
| 180 |
<!--/codeinclude-->
|
| 181 |
|
| 182 |
**Fields**:
|
| 183 |
-
- `tokens_used`:
|
| 184 |
-
- `tokens_limit`: Token limit
|
| 185 |
-
- `time_elapsed_seconds`:
|
| 186 |
-
- `time_limit_seconds`: Time limit
|
| 187 |
-
- `iterations`:
|
| 188 |
-
- `iterations_limit`:
|
|
|
|
| 189 |
|
| 190 |
## See Also
|
| 191 |
|
|
|
|
| 15 |
**Fields**:
|
| 16 |
- `citation`: Citation information (title, URL, date, authors)
|
| 17 |
- `content`: Evidence text content
|
| 18 |
+
- `relevance`: Relevance score (0.0-1.0)
|
| 19 |
- `metadata`: Additional metadata dictionary
|
| 20 |
|
| 21 |
## Citation
|
|
|
|
| 29 |
<!--/codeinclude-->
|
| 30 |
|
| 31 |
**Fields**:
|
| 32 |
+
- `source`: Source name (e.g., "pubmed", "clinicaltrials", "europepmc", "web", "rag")
|
| 33 |
- `title`: Article/trial title
|
| 34 |
- `url`: Source URL
|
| 35 |
+
- `date`: Publication date (YYYY-MM-DD or "Unknown")
|
| 36 |
- `authors`: List of authors (optional)
|
| 37 |
|
| 38 |
## KnowledgeGapOutput
|
|
|
|
| 73 |
<!--/codeinclude-->
|
| 74 |
|
| 75 |
**Fields**:
|
| 76 |
+
- `gap`: The knowledge gap being addressed (optional)
|
| 77 |
+
- `agent`: Name of agent to use
|
| 78 |
+
- `query`: The specific query for the agent
|
| 79 |
+
- `entity_website`: The website of the entity being researched, if known (optional)
|
| 80 |
|
| 81 |
## ReportDraft
|
| 82 |
|
|
|
|
| 89 |
<!--/codeinclude-->
|
| 90 |
|
| 91 |
**Fields**:
|
|
|
|
| 92 |
- `sections`: List of report sections
|
|
|
|
| 93 |
|
| 94 |
## ReportSection
|
| 95 |
|
|
|
|
| 102 |
<!--/codeinclude-->
|
| 103 |
|
| 104 |
**Fields**:
|
| 105 |
+
- `section_title`: The title of the section
|
| 106 |
+
- `section_content`: The content of the section
|
|
|
|
| 107 |
|
| 108 |
## ParsedQuery
|
| 109 |
|
|
|
|
| 133 |
<!--/codeinclude-->
|
| 134 |
|
| 135 |
**Fields**:
|
| 136 |
+
- `history`: List of iteration data
|
| 137 |
|
| 138 |
## IterationData
|
| 139 |
|
|
|
|
| 146 |
<!--/codeinclude-->
|
| 147 |
|
| 148 |
**Fields**:
|
| 149 |
+
- `gap`: The gap addressed in the iteration
|
| 150 |
+
- `tool_calls`: The tool calls made
|
| 151 |
+
- `findings`: The findings collected from tool calls
|
| 152 |
+
- `thought`: The thinking done to reflect on the success of the iteration and next steps
|
|
|
|
|
|
|
| 153 |
|
| 154 |
## AgentEvent
|
| 155 |
|
|
|
|
| 177 |
<!--/codeinclude-->
|
| 178 |
|
| 179 |
**Fields**:
|
| 180 |
+
- `tokens_used`: Total tokens used
|
| 181 |
+
- `tokens_limit`: Token budget limit
|
| 182 |
+
- `time_elapsed_seconds`: Time elapsed in seconds
|
| 183 |
+
- `time_limit_seconds`: Time budget limit (default: 600.0 seconds / 10 minutes)
|
| 184 |
+
- `iterations`: Number of iterations completed
|
| 185 |
+
- `iterations_limit`: Maximum iterations (default: 10)
|
| 186 |
+
- `iteration_tokens`: Tokens used per iteration (iteration number -> token count)
|
| 187 |
|
| 188 |
## See Also
|
| 189 |
|
docs/api/orchestrators.md
CHANGED
|
@@ -12,33 +12,21 @@ This page documents the API for DeepCritical orchestrators.
|
|
| 12 |
|
| 13 |
#### `run`
|
| 14 |
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
query: str,
|
| 19 |
-
background_context: str = "",
|
| 20 |
-
max_iterations: int | None = None,
|
| 21 |
-
max_time_minutes: float | None = None,
|
| 22 |
-
token_budget: int | None = None
|
| 23 |
-
) -> AsyncGenerator[AgentEvent, None]
|
| 24 |
-
```
|
| 25 |
|
| 26 |
Runs iterative research flow.
|
| 27 |
|
| 28 |
**Parameters**:
|
| 29 |
- `query`: Research query string
|
| 30 |
- `background_context`: Background context (default: "")
|
| 31 |
-
- `
|
| 32 |
-
- `
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
- `search_complete`: Search completed
|
| 38 |
-
- `judge_complete`: Evidence evaluation completed
|
| 39 |
-
- `synthesizing`: Generating report
|
| 40 |
-
- `complete`: Research completed
|
| 41 |
-
- `error`: Error occurred
|
| 42 |
|
| 43 |
## DeepResearchFlow
|
| 44 |
|
|
@@ -50,33 +38,18 @@ Runs iterative research flow.
|
|
| 50 |
|
| 51 |
#### `run`
|
| 52 |
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
query: str,
|
| 57 |
-
background_context: str = "",
|
| 58 |
-
max_iterations_per_section: int | None = None,
|
| 59 |
-
max_time_minutes: float | None = None,
|
| 60 |
-
token_budget: int | None = None
|
| 61 |
-
) -> AsyncGenerator[AgentEvent, None]
|
| 62 |
-
```
|
| 63 |
|
| 64 |
Runs deep research flow.
|
| 65 |
|
| 66 |
**Parameters**:
|
| 67 |
- `query`: Research query string
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
**Yields**: `AgentEvent` objects for:
|
| 74 |
-
- `started`: Research started
|
| 75 |
-
- `planning`: Creating research plan
|
| 76 |
-
- `looping`: Running parallel research loops
|
| 77 |
-
- `synthesizing`: Synthesizing results
|
| 78 |
-
- `complete`: Research completed
|
| 79 |
-
- `error`: Error occurred
|
| 80 |
|
| 81 |
## GraphOrchestrator
|
| 82 |
|
|
@@ -88,24 +61,19 @@ Runs deep research flow.
|
|
| 88 |
|
| 89 |
#### `run`
|
| 90 |
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
query: str,
|
| 95 |
-
research_mode: str = "auto",
|
| 96 |
-
use_graph: bool = True
|
| 97 |
-
) -> AsyncGenerator[AgentEvent, None]
|
| 98 |
-
```
|
| 99 |
|
| 100 |
Runs graph-based research orchestration.
|
| 101 |
|
| 102 |
**Parameters**:
|
| 103 |
- `query`: Research query string
|
| 104 |
-
- `research_mode`: Research mode ("iterative", "deep", or "auto")
|
| 105 |
-
- `use_graph`: Whether to use graph execution (default: True)
|
| 106 |
|
| 107 |
**Yields**: `AgentEvent` objects during graph execution.
|
| 108 |
|
|
|
|
|
|
|
| 109 |
## Orchestrator Factory
|
| 110 |
|
| 111 |
**Module**: `src.orchestrator_factory`
|
|
@@ -116,22 +84,18 @@ Runs graph-based research orchestration.
|
|
| 116 |
|
| 117 |
#### `create_orchestrator`
|
| 118 |
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
judge_handler: JudgeHandlerProtocol,
|
| 123 |
-
config: dict[str, Any],
|
| 124 |
-
mode: str | None = None
|
| 125 |
-
) -> Any
|
| 126 |
-
```
|
| 127 |
|
| 128 |
Creates an orchestrator instance.
|
| 129 |
|
| 130 |
**Parameters**:
|
| 131 |
-
- `search_handler`: Search handler protocol implementation
|
| 132 |
-
- `judge_handler`: Judge handler protocol implementation
|
| 133 |
-
- `config`: Configuration
|
| 134 |
-
- `mode`: Orchestrator mode ("simple", "advanced", "magentic", or None for auto-detect)
|
|
|
|
| 135 |
|
| 136 |
**Returns**: Orchestrator instance.
|
| 137 |
|
|
@@ -153,24 +117,19 @@ Creates an orchestrator instance.
|
|
| 153 |
|
| 154 |
#### `run`
|
| 155 |
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
query: str,
|
| 160 |
-
max_rounds: int = 15,
|
| 161 |
-
max_stalls: int = 3
|
| 162 |
-
) -> AsyncGenerator[AgentEvent, None]
|
| 163 |
-
```
|
| 164 |
|
| 165 |
Runs Magentic orchestration.
|
| 166 |
|
| 167 |
**Parameters**:
|
| 168 |
- `query`: Research query string
|
| 169 |
-
- `max_rounds`: Maximum rounds (default: 15)
|
| 170 |
-
- `max_stalls`: Maximum stalls before reset (default: 3)
|
| 171 |
|
| 172 |
**Yields**: `AgentEvent` objects converted from Magentic events.
|
| 173 |
|
|
|
|
|
|
|
| 174 |
**Requirements**:
|
| 175 |
- `agent-framework-core` package
|
| 176 |
- OpenAI API key
|
|
|
|
| 12 |
|
| 13 |
#### `run`
|
| 14 |
|
| 15 |
+
<!--codeinclude-->
|
| 16 |
+
[IterativeResearchFlow.run](../src/orchestrator/research_flow.py) start_line:134 end_line:140
|
| 17 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
Runs iterative research flow.
|
| 20 |
|
| 21 |
**Parameters**:
|
| 22 |
- `query`: Research query string
|
| 23 |
- `background_context`: Background context (default: "")
|
| 24 |
+
- `output_length`: Optional description of desired output length (default: "")
|
| 25 |
+
- `output_instructions`: Optional additional instructions for report generation (default: "")
|
| 26 |
+
|
| 27 |
+
**Returns**: Final report string.
|
| 28 |
+
|
| 29 |
+
**Note**: `max_iterations`, `max_time_minutes`, and `token_budget` are constructor parameters, not `run()` parameters.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
## DeepResearchFlow
|
| 32 |
|
|
|
|
| 38 |
|
| 39 |
#### `run`
|
| 40 |
|
| 41 |
+
<!--codeinclude-->
|
| 42 |
+
[DeepResearchFlow.run](../src/orchestrator/research_flow.py) start_line:778 end_line:778
|
| 43 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
Runs deep research flow.
|
| 46 |
|
| 47 |
**Parameters**:
|
| 48 |
- `query`: Research query string
|
| 49 |
+
|
| 50 |
+
**Returns**: Final report string.
|
| 51 |
+
|
| 52 |
+
**Note**: `max_iterations_per_section`, `max_time_minutes`, and `token_budget` are constructor parameters, not `run()` parameters.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
## GraphOrchestrator
|
| 55 |
|
|
|
|
| 61 |
|
| 62 |
#### `run`
|
| 63 |
|
| 64 |
+
<!--codeinclude-->
|
| 65 |
+
[GraphOrchestrator.run](../src/orchestrator/graph_orchestrator.py) start_line:177 end_line:177
|
| 66 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
Runs graph-based research orchestration.
|
| 69 |
|
| 70 |
**Parameters**:
|
| 71 |
- `query`: Research query string
|
|
|
|
|
|
|
| 72 |
|
| 73 |
**Yields**: `AgentEvent` objects during graph execution.
|
| 74 |
|
| 75 |
+
**Note**: `research_mode` and `use_graph` are constructor parameters, not `run()` parameters.
|
| 76 |
+
|
| 77 |
## Orchestrator Factory
|
| 78 |
|
| 79 |
**Module**: `src.orchestrator_factory`
|
|
|
|
| 84 |
|
| 85 |
#### `create_orchestrator`
|
| 86 |
|
| 87 |
+
<!--codeinclude-->
|
| 88 |
+
[create_orchestrator](../src/orchestrator_factory.py) start_line:44 end_line:50
|
| 89 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
Creates an orchestrator instance.
|
| 92 |
|
| 93 |
**Parameters**:
|
| 94 |
+
- `search_handler`: Search handler protocol implementation (optional, required for simple mode)
|
| 95 |
+
- `judge_handler`: Judge handler protocol implementation (optional, required for simple mode)
|
| 96 |
+
- `config`: Configuration object (optional)
|
| 97 |
+
- `mode`: Orchestrator mode ("simple", "advanced", "magentic", "iterative", "deep", "auto", or None for auto-detect)
|
| 98 |
+
- `oauth_token`: Optional OAuth token from HuggingFace login (takes priority over env vars)
|
| 99 |
|
| 100 |
**Returns**: Orchestrator instance.
|
| 101 |
|
|
|
|
| 117 |
|
| 118 |
#### `run`
|
| 119 |
|
| 120 |
+
<!--codeinclude-->
|
| 121 |
+
[MagenticOrchestrator.run](../src/orchestrator_magentic.py) start_line:101 end_line:101
|
| 122 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
|
| 124 |
Runs Magentic orchestration.
|
| 125 |
|
| 126 |
**Parameters**:
|
| 127 |
- `query`: Research query string
|
|
|
|
|
|
|
| 128 |
|
| 129 |
**Yields**: `AgentEvent` objects converted from Magentic events.
|
| 130 |
|
| 131 |
+
**Note**: `max_rounds` and `max_stalls` are constructor parameters, not `run()` parameters.
|
| 132 |
+
|
| 133 |
**Requirements**:
|
| 134 |
- `agent-framework-core` package
|
| 135 |
- OpenAI API key
|
docs/api/services.md
CHANGED
|
@@ -12,9 +12,9 @@ This page documents the API for DeepCritical services.
|
|
| 12 |
|
| 13 |
#### `embed`
|
| 14 |
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
|
| 19 |
Generates embedding for a text string.
|
| 20 |
|
|
@@ -68,6 +68,60 @@ Finds duplicate texts based on similarity threshold.
|
|
| 68 |
|
| 69 |
**Returns**: List of (index1, index2) tuples for duplicate pairs.
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
### Factory Function
|
| 72 |
|
| 73 |
#### `get_embedding_service`
|
|
@@ -89,63 +143,97 @@ Returns singleton EmbeddingService instance.
|
|
| 89 |
|
| 90 |
#### `ingest_evidence`
|
| 91 |
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
|
| 96 |
Ingests evidence into RAG service.
|
| 97 |
|
| 98 |
**Parameters**:
|
| 99 |
-
- `
|
| 100 |
|
| 101 |
-
**Note**:
|
| 102 |
|
| 103 |
#### `retrieve`
|
| 104 |
|
| 105 |
```python
|
| 106 |
-
|
| 107 |
self,
|
| 108 |
query: str,
|
| 109 |
-
top_k: int =
|
| 110 |
-
) -> list[
|
| 111 |
```
|
| 112 |
|
| 113 |
Retrieves relevant documents for a query.
|
| 114 |
|
| 115 |
**Parameters**:
|
| 116 |
- `query`: Search query string
|
| 117 |
-
- `top_k`: Number of top results to return (
|
| 118 |
|
| 119 |
-
**Returns**: List of
|
| 120 |
|
| 121 |
#### `query`
|
| 122 |
|
| 123 |
```python
|
| 124 |
-
|
| 125 |
self,
|
| 126 |
-
|
| 127 |
-
top_k: int =
|
| 128 |
) -> str
|
| 129 |
```
|
| 130 |
|
| 131 |
-
Queries RAG service and returns
|
| 132 |
|
| 133 |
**Parameters**:
|
| 134 |
-
- `
|
| 135 |
-
- `top_k`: Number of
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
### Factory Function
|
| 140 |
|
| 141 |
#### `get_rag_service`
|
| 142 |
|
| 143 |
```python
|
| 144 |
-
|
| 145 |
-
|
|
|
|
|
|
|
|
|
|
| 146 |
```
|
| 147 |
|
| 148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
|
| 150 |
## StatisticalAnalyzer
|
| 151 |
|
|
@@ -160,24 +248,27 @@ Returns singleton LlamaIndexRAGService instance, or None if OpenAI key not avail
|
|
| 160 |
```python
|
| 161 |
async def analyze(
|
| 162 |
self,
|
| 163 |
-
|
| 164 |
evidence: list[Evidence],
|
| 165 |
-
|
| 166 |
) -> AnalysisResult
|
| 167 |
```
|
| 168 |
|
| 169 |
-
Analyzes a
|
| 170 |
|
| 171 |
**Parameters**:
|
| 172 |
-
- `
|
| 173 |
-
- `evidence`: List of Evidence objects
|
| 174 |
-
- `
|
| 175 |
|
| 176 |
**Returns**: `AnalysisResult` with:
|
| 177 |
- `verdict`: SUPPORTED, REFUTED, or INCONCLUSIVE
|
| 178 |
-
- `
|
| 179 |
-
- `
|
| 180 |
-
- `
|
|
|
|
|
|
|
|
|
|
| 181 |
|
| 182 |
**Note**: Requires Modal credentials for sandbox execution.
|
| 183 |
|
|
|
|
| 12 |
|
| 13 |
#### `embed`
|
| 14 |
|
| 15 |
+
<!--codeinclude-->
|
| 16 |
+
[EmbeddingService.embed](../src/services/embeddings.py) start_line:55 end_line:55
|
| 17 |
+
<!--/codeinclude-->
|
| 18 |
|
| 19 |
Generates embedding for a text string.
|
| 20 |
|
|
|
|
| 68 |
|
| 69 |
**Returns**: List of (index1, index2) tuples for duplicate pairs.
|
| 70 |
|
| 71 |
+
#### `add_evidence`
|
| 72 |
+
|
| 73 |
+
```python
|
| 74 |
+
async def add_evidence(
|
| 75 |
+
self,
|
| 76 |
+
evidence_id: str,
|
| 77 |
+
content: str,
|
| 78 |
+
metadata: dict[str, Any]
|
| 79 |
+
) -> None
|
| 80 |
+
```
|
| 81 |
+
|
| 82 |
+
Adds evidence to vector store for semantic search.
|
| 83 |
+
|
| 84 |
+
**Parameters**:
|
| 85 |
+
- `evidence_id`: Unique identifier for the evidence
|
| 86 |
+
- `content`: Evidence text content
|
| 87 |
+
- `metadata`: Additional metadata dictionary
|
| 88 |
+
|
| 89 |
+
#### `search_similar`
|
| 90 |
+
|
| 91 |
+
```python
|
| 92 |
+
async def search_similar(
|
| 93 |
+
self,
|
| 94 |
+
query: str,
|
| 95 |
+
n_results: int = 5
|
| 96 |
+
) -> list[dict[str, Any]]
|
| 97 |
+
```
|
| 98 |
+
|
| 99 |
+
Finds semantically similar evidence.
|
| 100 |
+
|
| 101 |
+
**Parameters**:
|
| 102 |
+
- `query`: Search query string
|
| 103 |
+
- `n_results`: Number of results to return (default: 5)
|
| 104 |
+
|
| 105 |
+
**Returns**: List of dictionaries with `id`, `content`, `metadata`, and `distance` keys.
|
| 106 |
+
|
| 107 |
+
#### `deduplicate`
|
| 108 |
+
|
| 109 |
+
```python
|
| 110 |
+
async def deduplicate(
|
| 111 |
+
self,
|
| 112 |
+
new_evidence: list[Evidence],
|
| 113 |
+
threshold: float = 0.9
|
| 114 |
+
) -> list[Evidence]
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
Removes semantically duplicate evidence.
|
| 118 |
+
|
| 119 |
+
**Parameters**:
|
| 120 |
+
- `new_evidence`: List of evidence items to deduplicate
|
| 121 |
+
- `threshold`: Similarity threshold (default: 0.9, where 0.9 = 90% similar is duplicate)
|
| 122 |
+
|
| 123 |
+
**Returns**: List of unique evidence items (not already in vector store).
|
| 124 |
+
|
| 125 |
### Factory Function
|
| 126 |
|
| 127 |
#### `get_embedding_service`
|
|
|
|
| 143 |
|
| 144 |
#### `ingest_evidence`
|
| 145 |
|
| 146 |
+
<!--codeinclude-->
|
| 147 |
+
[LlamaIndexRAGService.ingest_evidence](../src/services/llamaindex_rag.py) start_line:290 end_line:290
|
| 148 |
+
<!--/codeinclude-->
|
| 149 |
|
| 150 |
Ingests evidence into RAG service.
|
| 151 |
|
| 152 |
**Parameters**:
|
| 153 |
+
- `evidence_list`: List of Evidence objects to ingest
|
| 154 |
|
| 155 |
+
**Note**: Supports multiple embedding providers (OpenAI, local sentence-transformers, Hugging Face).
|
| 156 |
|
| 157 |
#### `retrieve`
|
| 158 |
|
| 159 |
```python
|
| 160 |
+
def retrieve(
|
| 161 |
self,
|
| 162 |
query: str,
|
| 163 |
+
top_k: int | None = None
|
| 164 |
+
) -> list[dict[str, Any]]
|
| 165 |
```
|
| 166 |
|
| 167 |
Retrieves relevant documents for a query.
|
| 168 |
|
| 169 |
**Parameters**:
|
| 170 |
- `query`: Search query string
|
| 171 |
+
- `top_k`: Number of top results to return (defaults to `similarity_top_k` from constructor)
|
| 172 |
|
| 173 |
+
**Returns**: List of dictionaries with `text`, `score`, and `metadata` keys.
|
| 174 |
|
| 175 |
#### `query`
|
| 176 |
|
| 177 |
```python
|
| 178 |
+
def query(
|
| 179 |
self,
|
| 180 |
+
query_str: str,
|
| 181 |
+
top_k: int | None = None
|
| 182 |
) -> str
|
| 183 |
```
|
| 184 |
|
| 185 |
+
Queries RAG service and returns synthesized response.
|
| 186 |
|
| 187 |
**Parameters**:
|
| 188 |
+
- `query_str`: Query string
|
| 189 |
+
- `top_k`: Number of results to use (defaults to `similarity_top_k` from constructor)
|
| 190 |
+
|
| 191 |
+
**Returns**: Synthesized response string.
|
| 192 |
+
|
| 193 |
+
**Raises**:
|
| 194 |
+
- `ConfigurationError`: If no LLM API key is available for query synthesis
|
| 195 |
+
|
| 196 |
+
#### `ingest_documents`
|
| 197 |
+
|
| 198 |
+
```python
|
| 199 |
+
def ingest_documents(self, documents: list[Any]) -> None
|
| 200 |
+
```
|
| 201 |
|
| 202 |
+
Ingests raw LlamaIndex Documents.
|
| 203 |
+
|
| 204 |
+
**Parameters**:
|
| 205 |
+
- `documents`: List of LlamaIndex Document objects
|
| 206 |
+
|
| 207 |
+
#### `clear_collection`
|
| 208 |
+
|
| 209 |
+
```python
|
| 210 |
+
def clear_collection(self) -> None
|
| 211 |
+
```
|
| 212 |
+
|
| 213 |
+
Clears all documents from the collection.
|
| 214 |
|
| 215 |
### Factory Function
|
| 216 |
|
| 217 |
#### `get_rag_service`
|
| 218 |
|
| 219 |
```python
|
| 220 |
+
def get_rag_service(
|
| 221 |
+
collection_name: str = "deepcritical_evidence",
|
| 222 |
+
oauth_token: str | None = None,
|
| 223 |
+
**kwargs: Any
|
| 224 |
+
) -> LlamaIndexRAGService
|
| 225 |
```
|
| 226 |
|
| 227 |
+
Get or create a RAG service instance.
|
| 228 |
+
|
| 229 |
+
**Parameters**:
|
| 230 |
+
- `collection_name`: Name of the ChromaDB collection (default: "deepcritical_evidence")
|
| 231 |
+
- `oauth_token`: Optional OAuth token from HuggingFace login (takes priority over env vars)
|
| 232 |
+
- `**kwargs`: Additional arguments for LlamaIndexRAGService (e.g., `use_openai_embeddings=False`)
|
| 233 |
+
|
| 234 |
+
**Returns**: Configured LlamaIndexRAGService instance.
|
| 235 |
+
|
| 236 |
+
**Note**: By default, uses local embeddings (sentence-transformers) which require no API keys.
|
| 237 |
|
| 238 |
## StatisticalAnalyzer
|
| 239 |
|
|
|
|
| 248 |
```python
|
| 249 |
async def analyze(
|
| 250 |
self,
|
| 251 |
+
query: str,
|
| 252 |
evidence: list[Evidence],
|
| 253 |
+
hypothesis: dict[str, Any] | None = None
|
| 254 |
) -> AnalysisResult
|
| 255 |
```
|
| 256 |
|
| 257 |
+
Analyzes a research question using statistical methods.
|
| 258 |
|
| 259 |
**Parameters**:
|
| 260 |
+
- `query`: The research question
|
| 261 |
+
- `evidence`: List of Evidence objects to analyze
|
| 262 |
+
- `hypothesis`: Optional hypothesis dict with `drug`, `target`, `pathway`, `effect`, `confidence` keys
|
| 263 |
|
| 264 |
**Returns**: `AnalysisResult` with:
|
| 265 |
- `verdict`: SUPPORTED, REFUTED, or INCONCLUSIVE
|
| 266 |
+
- `confidence`: Confidence in verdict (0.0-1.0)
|
| 267 |
+
- `statistical_evidence`: Summary of statistical findings
|
| 268 |
+
- `code_generated`: Python code that was executed
|
| 269 |
+
- `execution_output`: Output from code execution
|
| 270 |
+
- `key_takeaways`: Key takeaways from analysis
|
| 271 |
+
- `limitations`: List of limitations
|
| 272 |
|
| 273 |
**Note**: Requires Modal credentials for sandbox execution.
|
| 274 |
|
docs/api/tools.md
CHANGED
|
@@ -56,8 +56,10 @@ Searches PubMed for articles.
|
|
| 56 |
**Returns**: List of `Evidence` objects with PubMed articles.
|
| 57 |
|
| 58 |
**Raises**:
|
| 59 |
-
- `SearchError`: If search fails
|
| 60 |
-
- `RateLimitError`: If rate limit is exceeded
|
|
|
|
|
|
|
| 61 |
|
| 62 |
## ClinicalTrialsTool
|
| 63 |
|
|
@@ -96,10 +98,10 @@ Searches ClinicalTrials.gov for trials.
|
|
| 96 |
|
| 97 |
**Returns**: List of `Evidence` objects with clinical trials.
|
| 98 |
|
| 99 |
-
**Note**: Only returns interventional studies with status: COMPLETED, ACTIVE_NOT_RECRUITING, RECRUITING, ENROLLING_BY_INVITATION
|
| 100 |
|
| 101 |
**Raises**:
|
| 102 |
-
- `SearchError`: If search fails
|
| 103 |
|
| 104 |
## EuropePMCTool
|
| 105 |
|
|
@@ -138,10 +140,10 @@ Searches Europe PMC for articles and preprints.
|
|
| 138 |
|
| 139 |
**Returns**: List of `Evidence` objects with articles/preprints.
|
| 140 |
|
| 141 |
-
**Note**: Includes both preprints (marked with `[PREPRINT - Not peer-reviewed]`) and peer-reviewed articles.
|
| 142 |
|
| 143 |
**Raises**:
|
| 144 |
-
- `SearchError`: If search fails
|
| 145 |
|
| 146 |
## RAGTool
|
| 147 |
|
|
@@ -149,6 +151,20 @@ Searches Europe PMC for articles and preprints.
|
|
| 149 |
|
| 150 |
**Purpose**: Semantic search within collected evidence.
|
| 151 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
### Properties
|
| 153 |
|
| 154 |
#### `name`
|
|
@@ -180,7 +196,10 @@ Searches collected evidence using semantic similarity.
|
|
| 180 |
|
| 181 |
**Returns**: List of `Evidence` objects from collected evidence.
|
| 182 |
|
| 183 |
-
**
|
|
|
|
|
|
|
|
|
|
| 184 |
|
| 185 |
## SearchHandler
|
| 186 |
|
|
@@ -188,32 +207,51 @@ Searches collected evidence using semantic similarity.
|
|
| 188 |
|
| 189 |
**Purpose**: Orchestrates parallel searches across multiple tools.
|
| 190 |
|
| 191 |
-
###
|
| 192 |
-
|
| 193 |
-
#### `search`
|
| 194 |
|
| 195 |
```python
|
| 196 |
-
|
| 197 |
self,
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
|
|
|
|
|
|
| 202 |
```
|
| 203 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
Searches multiple tools in parallel.
|
| 205 |
|
| 206 |
**Parameters**:
|
| 207 |
- `query`: Search query string
|
| 208 |
-
- `tools`: List of tools to use (default: all available tools)
|
| 209 |
- `max_results_per_tool`: Maximum results per tool (default: 10)
|
| 210 |
|
| 211 |
**Returns**: `SearchResult` with:
|
|
|
|
| 212 |
- `evidence`: Aggregated list of evidence
|
| 213 |
-
- `
|
| 214 |
-
- `
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
|
| 216 |
-
**Note**: Uses `asyncio.gather()` for parallel execution. Handles tool failures gracefully.
|
| 217 |
|
| 218 |
## See Also
|
| 219 |
|
|
|
|
| 56 |
**Returns**: List of `Evidence` objects with PubMed articles.
|
| 57 |
|
| 58 |
**Raises**:
|
| 59 |
+
- `SearchError`: If search fails (timeout, HTTP error, XML parsing error)
|
| 60 |
+
- `RateLimitError`: If rate limit is exceeded (429 status code)
|
| 61 |
+
|
| 62 |
+
**Note**: Uses NCBI E-utilities (ESearch → EFetch). Rate limit: 0.34s between requests. Handles single vs. multiple articles.
|
| 63 |
|
| 64 |
## ClinicalTrialsTool
|
| 65 |
|
|
|
|
| 98 |
|
| 99 |
**Returns**: List of `Evidence` objects with clinical trials.
|
| 100 |
|
| 101 |
+
**Note**: Only returns interventional studies with status: COMPLETED, ACTIVE_NOT_RECRUITING, RECRUITING, ENROLLING_BY_INVITATION. Uses `requests` library (NOT httpx - WAF blocks httpx). Runs in thread pool for async compatibility.
|
| 102 |
|
| 103 |
**Raises**:
|
| 104 |
+
- `SearchError`: If search fails (HTTP error, request exception)
|
| 105 |
|
| 106 |
## EuropePMCTool
|
| 107 |
|
|
|
|
| 140 |
|
| 141 |
**Returns**: List of `Evidence` objects with articles/preprints.
|
| 142 |
|
| 143 |
+
**Note**: Includes both preprints (marked with `[PREPRINT - Not peer-reviewed]`) and peer-reviewed articles. Handles preprint markers. Builds URLs from DOI or PMID.
|
| 144 |
|
| 145 |
**Raises**:
|
| 146 |
+
- `SearchError`: If search fails (HTTP error, connection error)
|
| 147 |
|
| 148 |
## RAGTool
|
| 149 |
|
|
|
|
| 151 |
|
| 152 |
**Purpose**: Semantic search within collected evidence.
|
| 153 |
|
| 154 |
+
### Initialization
|
| 155 |
+
|
| 156 |
+
```python
|
| 157 |
+
def __init__(
|
| 158 |
+
self,
|
| 159 |
+
rag_service: LlamaIndexRAGService | None = None,
|
| 160 |
+
oauth_token: str | None = None
|
| 161 |
+
) -> None
|
| 162 |
+
```
|
| 163 |
+
|
| 164 |
+
**Parameters**:
|
| 165 |
+
- `rag_service`: Optional RAG service instance. If None, will be lazy-initialized.
|
| 166 |
+
- `oauth_token`: Optional OAuth token from HuggingFace login (for RAG LLM)
|
| 167 |
+
|
| 168 |
### Properties
|
| 169 |
|
| 170 |
#### `name`
|
|
|
|
| 196 |
|
| 197 |
**Returns**: List of `Evidence` objects from collected evidence.
|
| 198 |
|
| 199 |
+
**Raises**:
|
| 200 |
+
- `ConfigurationError`: If RAG service is unavailable
|
| 201 |
+
|
| 202 |
+
**Note**: Requires evidence to be ingested into RAG service first. Wraps `LlamaIndexRAGService`. Returns Evidence from RAG results.
|
| 203 |
|
| 204 |
## SearchHandler
|
| 205 |
|
|
|
|
| 207 |
|
| 208 |
**Purpose**: Orchestrates parallel searches across multiple tools.
|
| 209 |
|
| 210 |
+
### Initialization
|
|
|
|
|
|
|
| 211 |
|
| 212 |
```python
|
| 213 |
+
def __init__(
|
| 214 |
self,
|
| 215 |
+
tools: list[SearchTool],
|
| 216 |
+
timeout: float = 30.0,
|
| 217 |
+
include_rag: bool = False,
|
| 218 |
+
auto_ingest_to_rag: bool = True,
|
| 219 |
+
oauth_token: str | None = None
|
| 220 |
+
) -> None
|
| 221 |
```
|
| 222 |
|
| 223 |
+
**Parameters**:
|
| 224 |
+
- `tools`: List of search tools to use
|
| 225 |
+
- `timeout`: Timeout for each search in seconds (default: 30.0)
|
| 226 |
+
- `include_rag`: Whether to include RAG tool in searches (default: False)
|
| 227 |
+
- `auto_ingest_to_rag`: Whether to automatically ingest results into RAG (default: True)
|
| 228 |
+
- `oauth_token`: Optional OAuth token from HuggingFace login (for RAG LLM)
|
| 229 |
+
|
| 230 |
+
### Methods
|
| 231 |
+
|
| 232 |
+
#### `execute`
|
| 233 |
+
|
| 234 |
+
<!--codeinclude-->
|
| 235 |
+
[SearchHandler.execute](../src/tools/search_handler.py) start_line:86 end_line:86
|
| 236 |
+
<!--/codeinclude-->
|
| 237 |
+
|
| 238 |
Searches multiple tools in parallel.
|
| 239 |
|
| 240 |
**Parameters**:
|
| 241 |
- `query`: Search query string
|
|
|
|
| 242 |
- `max_results_per_tool`: Maximum results per tool (default: 10)
|
| 243 |
|
| 244 |
**Returns**: `SearchResult` with:
|
| 245 |
+
- `query`: The search query
|
| 246 |
- `evidence`: Aggregated list of evidence
|
| 247 |
+
- `sources_searched`: List of source names searched
|
| 248 |
+
- `total_found`: Total number of results
|
| 249 |
+
- `errors`: List of error messages from failed tools
|
| 250 |
+
|
| 251 |
+
**Raises**:
|
| 252 |
+
- `SearchError`: If search times out
|
| 253 |
|
| 254 |
+
**Note**: Uses `asyncio.gather()` for parallel execution. Handles tool failures gracefully (returns errors in `SearchResult.errors`). Automatically ingests evidence into RAG if enabled.
|
| 255 |
|
| 256 |
## See Also
|
| 257 |
|
docs/architecture/agents.md
CHANGED
|
@@ -4,12 +4,16 @@ DeepCritical uses Pydantic AI agents for all AI-powered operations. All agents f
|
|
| 4 |
|
| 5 |
## Agent Pattern
|
| 6 |
|
| 7 |
-
|
|
|
|
|
|
|
| 8 |
|
| 9 |
- **System Prompt**: Module-level constant with date injection
|
| 10 |
- **Agent Class**: `__init__(model: Any | None = None)`
|
| 11 |
- **Main Method**: Async method (e.g., `async def evaluate()`, `async def write_report()`)
|
| 12 |
-
- **Factory Function**: `def create_agent_name(model: Any | None = None) -> AgentName`
|
|
|
|
|
|
|
| 13 |
|
| 14 |
## Model Initialization
|
| 15 |
|
|
@@ -155,43 +159,135 @@ For text output (writer agents), agents return `str` directly.
|
|
| 155 |
- `key_entities`: List of key entities
|
| 156 |
- `research_questions`: List of research questions
|
| 157 |
|
| 158 |
-
##
|
| 159 |
|
| 160 |
-
|
| 161 |
|
| 162 |
-
|
| 163 |
-
[Factory Functions](../src/agent_factory/agents.py) start_line:77 end_line:97
|
| 164 |
-
<!--/codeinclude-->
|
| 165 |
|
| 166 |
-
|
| 167 |
-
- Use `get_model()` if no model provided
|
| 168 |
-
- Raise `ConfigurationError` if creation fails
|
| 169 |
-
- Log agent creation
|
| 170 |
|
| 171 |
-
|
| 172 |
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
|
|
|
|
| 179 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
|
|
|
|
| 181 |
|
|
|
|
| 182 |
|
|
|
|
| 183 |
|
|
|
|
|
|
|
| 184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
|
|
|
|
| 186 |
|
|
|
|
| 187 |
|
|
|
|
| 188 |
|
|
|
|
| 189 |
|
|
|
|
|
|
|
|
|
|
| 190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
|
|
|
|
| 192 |
|
|
|
|
| 193 |
|
|
|
|
| 194 |
|
|
|
|
| 195 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
## Agent Pattern
|
| 6 |
|
| 7 |
+
### Pydantic AI Agents
|
| 8 |
+
|
| 9 |
+
Pydantic AI agents use the `Agent` class with the following structure:
|
| 10 |
|
| 11 |
- **System Prompt**: Module-level constant with date injection
|
| 12 |
- **Agent Class**: `__init__(model: Any | None = None)`
|
| 13 |
- **Main Method**: Async method (e.g., `async def evaluate()`, `async def write_report()`)
|
| 14 |
+
- **Factory Function**: `def create_agent_name(model: Any | None = None, oauth_token: str | None = None) -> AgentName`
|
| 15 |
+
|
| 16 |
+
**Note**: Factory functions accept an optional `oauth_token` parameter for HuggingFace authentication, which takes priority over environment variables.
|
| 17 |
|
| 18 |
## Model Initialization
|
| 19 |
|
|
|
|
| 159 |
- `key_entities`: List of key entities
|
| 160 |
- `research_questions`: List of research questions
|
| 161 |
|
| 162 |
+
## Magentic Agents
|
| 163 |
|
| 164 |
+
The following agents use the `BaseAgent` pattern from `agent-framework` and are used exclusively with `MagenticOrchestrator`:
|
| 165 |
|
| 166 |
+
### Hypothesis Agent
|
|
|
|
|
|
|
| 167 |
|
| 168 |
+
**File**: `src/agents/hypothesis_agent.py`
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
+
**Purpose**: Generates mechanistic hypotheses based on evidence.
|
| 171 |
|
| 172 |
+
**Pattern**: `BaseAgent` from `agent-framework`
|
| 173 |
+
|
| 174 |
+
**Methods**:
|
| 175 |
+
- `async def run(messages, thread, **kwargs) -> AgentRunResponse`
|
| 176 |
+
|
| 177 |
+
**Features**:
|
| 178 |
+
- Uses internal Pydantic AI `Agent` with `HypothesisAssessment` output type
|
| 179 |
+
- Accesses shared `evidence_store` for evidence
|
| 180 |
+
- Uses embedding service for diverse evidence selection (MMR algorithm)
|
| 181 |
+
- Stores hypotheses in shared context
|
| 182 |
+
|
| 183 |
+
### Search Agent
|
| 184 |
+
|
| 185 |
+
**File**: `src/agents/search_agent.py`
|
| 186 |
+
|
| 187 |
+
**Purpose**: Wraps `SearchHandler` as an agent for Magentic orchestrator.
|
| 188 |
+
|
| 189 |
+
**Pattern**: `BaseAgent` from `agent-framework`
|
| 190 |
+
|
| 191 |
+
**Methods**:
|
| 192 |
+
- `async def run(messages, thread, **kwargs) -> AgentRunResponse`
|
| 193 |
+
|
| 194 |
+
**Features**:
|
| 195 |
+
- Executes searches via `SearchHandlerProtocol`
|
| 196 |
+
- Deduplicates evidence using embedding service
|
| 197 |
+
- Searches for semantically related evidence
|
| 198 |
+
- Updates shared evidence store
|
| 199 |
+
|
| 200 |
+
### Analysis Agent
|
| 201 |
+
|
| 202 |
+
**File**: `src/agents/analysis_agent.py`
|
| 203 |
+
|
| 204 |
+
**Purpose**: Performs statistical analysis using Modal sandbox.
|
| 205 |
|
| 206 |
+
**Pattern**: `BaseAgent` from `agent-framework`
|
| 207 |
|
| 208 |
+
**Methods**:
|
| 209 |
+
- `async def run(messages, thread, **kwargs) -> AgentRunResponse`
|
| 210 |
+
|
| 211 |
+
**Features**:
|
| 212 |
+
- Wraps `StatisticalAnalyzer` service
|
| 213 |
+
- Analyzes evidence and hypotheses
|
| 214 |
+
- Returns verdict (SUPPORTED/REFUTED/INCONCLUSIVE)
|
| 215 |
+
- Stores analysis results in shared context
|
| 216 |
+
|
| 217 |
+
### Report Agent (Magentic)
|
| 218 |
|
| 219 |
+
**File**: `src/agents/report_agent.py`
|
| 220 |
|
| 221 |
+
**Purpose**: Generates structured scientific reports from evidence and hypotheses.
|
| 222 |
|
| 223 |
+
**Pattern**: `BaseAgent` from `agent-framework`
|
| 224 |
|
| 225 |
+
**Methods**:
|
| 226 |
+
- `async def run(messages, thread, **kwargs) -> AgentRunResponse`
|
| 227 |
|
| 228 |
+
**Features**:
|
| 229 |
+
- Uses internal Pydantic AI `Agent` with `ResearchReport` output type
|
| 230 |
+
- Accesses shared evidence store and hypotheses
|
| 231 |
+
- Validates citations before returning
|
| 232 |
+
- Formats report as markdown
|
| 233 |
|
| 234 |
+
### Judge Agent
|
| 235 |
|
| 236 |
+
**File**: `src/agents/judge_agent.py`
|
| 237 |
|
| 238 |
+
**Purpose**: Evaluates evidence quality and determines if sufficient for synthesis.
|
| 239 |
|
| 240 |
+
**Pattern**: `BaseAgent` from `agent-framework`
|
| 241 |
|
| 242 |
+
**Methods**:
|
| 243 |
+
- `async def run(messages, thread, **kwargs) -> AgentRunResponse`
|
| 244 |
+
- `async def run_stream(messages, thread, **kwargs) -> AsyncIterable[AgentRunResponseUpdate]`
|
| 245 |
|
| 246 |
+
**Features**:
|
| 247 |
+
- Wraps `JudgeHandlerProtocol`
|
| 248 |
+
- Accesses shared evidence store
|
| 249 |
+
- Returns `JudgeAssessment` with sufficient flag, confidence, and recommendation
|
| 250 |
|
| 251 |
+
## Agent Patterns
|
| 252 |
|
| 253 |
+
DeepCritical uses two distinct agent patterns:
|
| 254 |
|
| 255 |
+
### 1. Pydantic AI Agents (Traditional Pattern)
|
| 256 |
|
| 257 |
+
These agents use the Pydantic AI `Agent` class directly and are used in iterative and deep research flows:
|
| 258 |
|
| 259 |
+
- **Pattern**: `Agent(model, output_type, system_prompt)`
|
| 260 |
+
- **Initialization**: `__init__(model: Any | None = None)`
|
| 261 |
+
- **Methods**: Agent-specific async methods (e.g., `async def evaluate()`, `async def write_report()`)
|
| 262 |
+
- **Examples**: `KnowledgeGapAgent`, `ToolSelectorAgent`, `WriterAgent`, `LongWriterAgent`, `ProofreaderAgent`, `ThinkingAgent`, `InputParserAgent`
|
| 263 |
|
| 264 |
+
### 2. Magentic Agents (Agent-Framework Pattern)
|
| 265 |
+
|
| 266 |
+
These agents use the `BaseAgent` class from `agent-framework` and are used in Magentic orchestrator:
|
| 267 |
+
|
| 268 |
+
- **Pattern**: `BaseAgent` from `agent-framework` with `async def run()` method
|
| 269 |
+
- **Initialization**: `__init__(evidence_store, embedding_service, ...)`
|
| 270 |
+
- **Methods**: `async def run(messages, thread, **kwargs) -> AgentRunResponse`
|
| 271 |
+
- **Examples**: `HypothesisAgent`, `SearchAgent`, `AnalysisAgent`, `ReportAgent`, `JudgeAgent`
|
| 272 |
+
|
| 273 |
+
**Note**: Magentic agents are used exclusively with the `MagenticOrchestrator` and follow the agent-framework protocol for multi-agent coordination.
|
| 274 |
+
|
| 275 |
+
## Factory Functions
|
| 276 |
+
|
| 277 |
+
All agents have factory functions in `src/agent_factory/agents.py`:
|
| 278 |
+
|
| 279 |
+
<!--codeinclude-->
|
| 280 |
+
[Factory Functions](../src/agent_factory/agents.py) start_line:79 end_line:100
|
| 281 |
+
<!--/codeinclude-->
|
| 282 |
+
|
| 283 |
+
Factory functions:
|
| 284 |
+
- Use `get_model()` if no model provided
|
| 285 |
+
- Accept `oauth_token` parameter for HuggingFace authentication
|
| 286 |
+
- Raise `ConfigurationError` if creation fails
|
| 287 |
+
- Log agent creation
|
| 288 |
+
|
| 289 |
+
## See Also
|
| 290 |
+
|
| 291 |
+
- [Orchestrators](orchestrators.md) - How agents are orchestrated
|
| 292 |
+
- [API Reference - Agents](../api/agents.md) - API documentation
|
| 293 |
+
- [Contributing - Code Style](../contributing/code-style.md) - Development guidelines
|
docs/architecture/graph-orchestration.md
DELETED
|
@@ -1,138 +0,0 @@
|
|
| 1 |
-
# Graph Orchestration Architecture
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
Phase 4 implements a graph-based orchestration system for research workflows using Pydantic AI agents as nodes. This enables better parallel execution, conditional routing, and state management compared to simple agent chains.
|
| 6 |
-
|
| 7 |
-
## Graph Structure
|
| 8 |
-
|
| 9 |
-
### Nodes
|
| 10 |
-
|
| 11 |
-
Graph nodes represent different stages in the research workflow:
|
| 12 |
-
|
| 13 |
-
1. **Agent Nodes**: Execute Pydantic AI agents
|
| 14 |
-
- Input: Prompt/query
|
| 15 |
-
- Output: Structured or unstructured response
|
| 16 |
-
- Examples: `KnowledgeGapAgent`, `ToolSelectorAgent`, `ThinkingAgent`
|
| 17 |
-
|
| 18 |
-
2. **State Nodes**: Update or read workflow state
|
| 19 |
-
- Input: Current state
|
| 20 |
-
- Output: Updated state
|
| 21 |
-
- Examples: Update evidence, update conversation history
|
| 22 |
-
|
| 23 |
-
3. **Decision Nodes**: Make routing decisions based on conditions
|
| 24 |
-
- Input: Current state/results
|
| 25 |
-
- Output: Next node ID
|
| 26 |
-
- Examples: Continue research vs. complete research
|
| 27 |
-
|
| 28 |
-
4. **Parallel Nodes**: Execute multiple nodes concurrently
|
| 29 |
-
- Input: List of node IDs
|
| 30 |
-
- Output: Aggregated results
|
| 31 |
-
- Examples: Parallel iterative research loops
|
| 32 |
-
|
| 33 |
-
### Edges
|
| 34 |
-
|
| 35 |
-
Edges define transitions between nodes:
|
| 36 |
-
|
| 37 |
-
1. **Sequential Edges**: Always traversed (no condition)
|
| 38 |
-
- From: Source node
|
| 39 |
-
- To: Target node
|
| 40 |
-
- Condition: None (always True)
|
| 41 |
-
|
| 42 |
-
2. **Conditional Edges**: Traversed based on condition
|
| 43 |
-
- From: Source node
|
| 44 |
-
- To: Target node
|
| 45 |
-
- Condition: Callable that returns bool
|
| 46 |
-
- Example: If research complete → go to writer, else → continue loop
|
| 47 |
-
|
| 48 |
-
3. **Parallel Edges**: Used for parallel execution branches
|
| 49 |
-
- From: Parallel node
|
| 50 |
-
- To: Multiple target nodes
|
| 51 |
-
- Execution: All targets run concurrently
|
| 52 |
-
|
| 53 |
-
## Graph Patterns
|
| 54 |
-
|
| 55 |
-
### Iterative Research Graph
|
| 56 |
-
|
| 57 |
-
```
|
| 58 |
-
[Input] → [Thinking] → [Knowledge Gap] → [Decision: Complete?]
|
| 59 |
-
↓ No ↓ Yes
|
| 60 |
-
[Tool Selector] [Writer]
|
| 61 |
-
↓
|
| 62 |
-
[Execute Tools] → [Loop Back]
|
| 63 |
-
```
|
| 64 |
-
|
| 65 |
-
### Deep Research Graph
|
| 66 |
-
|
| 67 |
-
```
|
| 68 |
-
[Input] → [Planner] → [Parallel Iterative Loops] → [Synthesizer]
|
| 69 |
-
↓ ↓ ↓
|
| 70 |
-
[Loop1] [Loop2] [Loop3]
|
| 71 |
-
```
|
| 72 |
-
|
| 73 |
-
## State Management
|
| 74 |
-
|
| 75 |
-
State is managed via `WorkflowState` using `ContextVar` for thread-safe isolation:
|
| 76 |
-
|
| 77 |
-
- **Evidence**: Collected evidence from searches
|
| 78 |
-
- **Conversation**: Iteration history (gaps, tool calls, findings, thoughts)
|
| 79 |
-
- **Embedding Service**: For semantic search
|
| 80 |
-
|
| 81 |
-
State transitions occur at state nodes, which update the global workflow state.
|
| 82 |
-
|
| 83 |
-
## Execution Flow
|
| 84 |
-
|
| 85 |
-
1. **Graph Construction**: Build graph from nodes and edges
|
| 86 |
-
2. **Graph Validation**: Ensure graph is valid (no cycles, all nodes reachable)
|
| 87 |
-
3. **Graph Execution**: Traverse graph from entry node
|
| 88 |
-
4. **Node Execution**: Execute each node based on type
|
| 89 |
-
5. **Edge Evaluation**: Determine next node(s) based on edges
|
| 90 |
-
6. **Parallel Execution**: Use `asyncio.gather()` for parallel nodes
|
| 91 |
-
7. **State Updates**: Update state at state nodes
|
| 92 |
-
8. **Event Streaming**: Yield events during execution for UI
|
| 93 |
-
|
| 94 |
-
## Conditional Routing
|
| 95 |
-
|
| 96 |
-
Decision nodes evaluate conditions and return next node IDs:
|
| 97 |
-
|
| 98 |
-
- **Knowledge Gap Decision**: If `research_complete` → writer, else → tool selector
|
| 99 |
-
- **Budget Decision**: If budget exceeded → exit, else → continue
|
| 100 |
-
- **Iteration Decision**: If max iterations → exit, else → continue
|
| 101 |
-
|
| 102 |
-
## Parallel Execution
|
| 103 |
-
|
| 104 |
-
Parallel nodes execute multiple nodes concurrently:
|
| 105 |
-
|
| 106 |
-
- Each parallel branch runs independently
|
| 107 |
-
- Results are aggregated after all branches complete
|
| 108 |
-
- State is synchronized after parallel execution
|
| 109 |
-
- Errors in one branch don't stop other branches
|
| 110 |
-
|
| 111 |
-
## Budget Enforcement
|
| 112 |
-
|
| 113 |
-
Budget constraints are enforced at decision nodes:
|
| 114 |
-
|
| 115 |
-
- **Token Budget**: Track LLM token usage
|
| 116 |
-
- **Time Budget**: Track elapsed time
|
| 117 |
-
- **Iteration Budget**: Track iteration count
|
| 118 |
-
|
| 119 |
-
If any budget is exceeded, execution routes to exit node.
|
| 120 |
-
|
| 121 |
-
## Error Handling
|
| 122 |
-
|
| 123 |
-
Errors are handled at multiple levels:
|
| 124 |
-
|
| 125 |
-
1. **Node Level**: Catch errors in individual node execution
|
| 126 |
-
2. **Graph Level**: Handle errors during graph traversal
|
| 127 |
-
3. **State Level**: Rollback state changes on error
|
| 128 |
-
|
| 129 |
-
Errors are logged and yield error events for UI.
|
| 130 |
-
|
| 131 |
-
## Backward Compatibility
|
| 132 |
-
|
| 133 |
-
Graph execution is optional via feature flag:
|
| 134 |
-
|
| 135 |
-
- `USE_GRAPH_EXECUTION=true`: Use graph-based execution
|
| 136 |
-
- `USE_GRAPH_EXECUTION=false`: Use agent chain execution (existing)
|
| 137 |
-
|
| 138 |
-
This allows gradual migration and fallback if needed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/architecture/graph_orchestration.md
CHANGED
|
@@ -1,9 +1,15 @@
|
|
| 1 |
# Graph Orchestration Architecture
|
| 2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
## Graph Patterns
|
| 4 |
|
| 5 |
### Iterative Research Graph
|
| 6 |
|
|
|
|
|
|
|
| 7 |
```
|
| 8 |
[Input] → [Thinking] → [Knowledge Gap] → [Decision: Complete?]
|
| 9 |
↓ No ↓ Yes
|
|
@@ -12,14 +18,31 @@
|
|
| 12 |
[Execute Tools] → [Loop Back]
|
| 13 |
```
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
### Deep Research Graph
|
| 16 |
|
|
|
|
|
|
|
| 17 |
```
|
| 18 |
-
[Input] → [Planner] → [Parallel
|
| 19 |
-
|
| 20 |
-
|
| 21 |
```
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
### Deep Research
|
| 24 |
|
| 25 |
```mermaid
|
|
@@ -158,14 +181,35 @@ State transitions occur at state nodes, which update the global workflow state.
|
|
| 158 |
|
| 159 |
## Execution Flow
|
| 160 |
|
| 161 |
-
1. **Graph Construction**: Build graph from nodes and edges
|
| 162 |
-
2. **Graph Validation**: Ensure graph is valid (no cycles, all nodes reachable)
|
| 163 |
-
3. **Graph Execution**: Traverse graph from entry node
|
| 164 |
-
4. **Node Execution**: Execute each node based on type
|
| 165 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
6. **Parallel Execution**: Use `asyncio.gather()` for parallel nodes
|
| 167 |
-
7. **State Updates**: Update state at state nodes
|
| 168 |
-
8. **Event Streaming**: Yield
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
## Conditional Routing
|
| 171 |
|
|
|
|
| 1 |
# Graph Orchestration Architecture
|
| 2 |
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
DeepCritical implements a graph-based orchestration system for research workflows using Pydantic AI agents as nodes. This enables better parallel execution, conditional routing, and state management compared to simple agent chains.
|
| 6 |
+
|
| 7 |
## Graph Patterns
|
| 8 |
|
| 9 |
### Iterative Research Graph
|
| 10 |
|
| 11 |
+
The iterative research graph follows this pattern:
|
| 12 |
+
|
| 13 |
```
|
| 14 |
[Input] → [Thinking] → [Knowledge Gap] → [Decision: Complete?]
|
| 15 |
↓ No ↓ Yes
|
|
|
|
| 18 |
[Execute Tools] → [Loop Back]
|
| 19 |
```
|
| 20 |
|
| 21 |
+
**Node IDs**: `thinking` → `knowledge_gap` → `continue_decision` → `tool_selector`/`writer` → `execute_tools` → (loop back to `thinking`)
|
| 22 |
+
|
| 23 |
+
**Special Node Handling**:
|
| 24 |
+
- `execute_tools`: State node that uses `search_handler` to execute searches and add evidence to workflow state
|
| 25 |
+
- `continue_decision`: Decision node that routes based on `research_complete` flag from `KnowledgeGapOutput`
|
| 26 |
+
|
| 27 |
### Deep Research Graph
|
| 28 |
|
| 29 |
+
The deep research graph follows this pattern:
|
| 30 |
+
|
| 31 |
```
|
| 32 |
+
[Input] → [Planner] → [Store Plan] → [Parallel Loops] → [Collect Drafts] → [Synthesizer]
|
| 33 |
+
↓ ↓ ↓
|
| 34 |
+
[Loop1] [Loop2] [Loop3]
|
| 35 |
```
|
| 36 |
|
| 37 |
+
**Node IDs**: `planner` → `store_plan` → `parallel_loops` → `collect_drafts` → `synthesizer`
|
| 38 |
+
|
| 39 |
+
**Special Node Handling**:
|
| 40 |
+
- `planner`: Agent node that creates `ReportPlan` with report outline
|
| 41 |
+
- `store_plan`: State node that stores `ReportPlan` in context for parallel loops
|
| 42 |
+
- `parallel_loops`: Parallel node that executes `IterativeResearchFlow` instances for each section
|
| 43 |
+
- `collect_drafts`: State node that collects section drafts from parallel loops
|
| 44 |
+
- `synthesizer`: Agent node that calls `LongWriterAgent.write_report()` directly with `ReportDraft`
|
| 45 |
+
|
| 46 |
### Deep Research
|
| 47 |
|
| 48 |
```mermaid
|
|
|
|
| 181 |
|
| 182 |
## Execution Flow
|
| 183 |
|
| 184 |
+
1. **Graph Construction**: Build graph from nodes and edges using `create_iterative_graph()` or `create_deep_graph()`
|
| 185 |
+
2. **Graph Validation**: Ensure graph is valid (no cycles, all nodes reachable) via `ResearchGraph.validate_structure()`
|
| 186 |
+
3. **Graph Execution**: Traverse graph from entry node using `GraphOrchestrator._execute_graph()`
|
| 187 |
+
4. **Node Execution**: Execute each node based on type:
|
| 188 |
+
- **Agent Nodes**: Call `agent.run()` with transformed input
|
| 189 |
+
- **State Nodes**: Update workflow state via `state_updater` function
|
| 190 |
+
- **Decision Nodes**: Evaluate `decision_function` to get next node ID
|
| 191 |
+
- **Parallel Nodes**: Execute all parallel nodes concurrently via `asyncio.gather()`
|
| 192 |
+
5. **Edge Evaluation**: Determine next node(s) based on edges and conditions
|
| 193 |
6. **Parallel Execution**: Use `asyncio.gather()` for parallel nodes
|
| 194 |
+
7. **State Updates**: Update state at state nodes via `GraphExecutionContext.update_state()`
|
| 195 |
+
8. **Event Streaming**: Yield `AgentEvent` objects during execution for UI
|
| 196 |
+
|
| 197 |
+
### GraphExecutionContext
|
| 198 |
+
|
| 199 |
+
The `GraphExecutionContext` class manages execution state during graph traversal:
|
| 200 |
+
|
| 201 |
+
- **State**: Current `WorkflowState` instance
|
| 202 |
+
- **Budget Tracker**: `BudgetTracker` instance for budget enforcement
|
| 203 |
+
- **Node Results**: Dictionary storing results from each node execution
|
| 204 |
+
- **Visited Nodes**: Set of node IDs that have been executed
|
| 205 |
+
- **Current Node**: ID of the node currently being executed
|
| 206 |
+
|
| 207 |
+
Methods:
|
| 208 |
+
- `set_node_result(node_id, result)`: Store result from node execution
|
| 209 |
+
- `get_node_result(node_id)`: Retrieve stored result
|
| 210 |
+
- `has_visited(node_id)`: Check if node was visited
|
| 211 |
+
- `mark_visited(node_id)`: Mark node as visited
|
| 212 |
+
- `update_state(updater, data)`: Update workflow state
|
| 213 |
|
| 214 |
## Conditional Routing
|
| 215 |
|
docs/architecture/middleware.md
CHANGED
|
@@ -18,8 +18,8 @@ DeepCritical uses middleware for state management, budget tracking, and workflow
|
|
| 18 |
- `embedding_service: Any`: Embedding service for semantic search
|
| 19 |
|
| 20 |
**Methods**:
|
| 21 |
-
- `add_evidence(
|
| 22 |
-
- `async search_related(query: str,
|
| 23 |
|
| 24 |
**Initialization**:
|
| 25 |
|
|
@@ -30,7 +30,7 @@ DeepCritical uses middleware for state management, budget tracking, and workflow
|
|
| 30 |
**Access**:
|
| 31 |
|
| 32 |
<!--codeinclude-->
|
| 33 |
-
[Get Workflow State](../src/middleware/state_machine.py) start_line:
|
| 34 |
<!--/codeinclude-->
|
| 35 |
|
| 36 |
## Workflow Manager
|
|
@@ -40,10 +40,10 @@ DeepCritical uses middleware for state management, budget tracking, and workflow
|
|
| 40 |
**Purpose**: Coordinates parallel research loops
|
| 41 |
|
| 42 |
**Methods**:
|
| 43 |
-
- `add_loop(
|
| 44 |
-
- `async run_loops_parallel() -> list[
|
| 45 |
-
- `update_loop_status(loop_id: str, status: str)`: Update loop status
|
| 46 |
-
- `sync_loop_evidence_to_state()`: Synchronize evidence from
|
| 47 |
|
| 48 |
**Features**:
|
| 49 |
- Uses `asyncio.gather()` for parallel execution
|
|
@@ -56,9 +56,22 @@ DeepCritical uses middleware for state management, budget tracking, and workflow
|
|
| 56 |
from src.middleware.workflow_manager import WorkflowManager
|
| 57 |
|
| 58 |
manager = WorkflowManager()
|
| 59 |
-
manager.add_loop(loop1)
|
| 60 |
-
manager.add_loop(loop2)
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
```
|
| 63 |
|
| 64 |
## Budget Tracker
|
|
@@ -73,13 +86,13 @@ completed_loops = await manager.run_loops_parallel()
|
|
| 73 |
- **Iterations**: Number of iterations
|
| 74 |
|
| 75 |
**Methods**:
|
| 76 |
-
- `create_budget(
|
| 77 |
-
- `add_tokens(tokens: int)`: Add token usage
|
| 78 |
-
- `start_timer()`: Start time tracking
|
| 79 |
-
- `update_timer()`: Update elapsed time
|
| 80 |
-
- `increment_iteration()`: Increment iteration count
|
| 81 |
-
- `check_budget() ->
|
| 82 |
-
- `can_continue() -> bool`: Check if
|
| 83 |
|
| 84 |
**Token Estimation**:
|
| 85 |
- `estimate_tokens(text: str) -> int`: ~4 chars per token
|
|
@@ -91,13 +104,20 @@ from src.middleware.budget_tracker import BudgetTracker
|
|
| 91 |
|
| 92 |
tracker = BudgetTracker()
|
| 93 |
budget = tracker.create_budget(
|
| 94 |
-
|
|
|
|
| 95 |
time_limit_seconds=600,
|
| 96 |
iterations_limit=10
|
| 97 |
)
|
| 98 |
-
tracker.start_timer()
|
| 99 |
# ... research operations ...
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
# Budget exceeded, stop research
|
| 102 |
pass
|
| 103 |
```
|
|
|
|
| 18 |
- `embedding_service: Any`: Embedding service for semantic search
|
| 19 |
|
| 20 |
**Methods**:
|
| 21 |
+
- `add_evidence(new_evidence: list[Evidence]) -> int`: Adds evidence with URL-based deduplication. Returns the number of new items added (excluding duplicates).
|
| 22 |
+
- `async search_related(query: str, n_results: int = 5) -> list[Evidence]`: Semantic search for related evidence using embedding service
|
| 23 |
|
| 24 |
**Initialization**:
|
| 25 |
|
|
|
|
| 30 |
**Access**:
|
| 31 |
|
| 32 |
<!--codeinclude-->
|
| 33 |
+
[Get Workflow State](../src/middleware/state_machine.py) start_line:115 end_line:129
|
| 34 |
<!--/codeinclude-->
|
| 35 |
|
| 36 |
## Workflow Manager
|
|
|
|
| 40 |
**Purpose**: Coordinates parallel research loops
|
| 41 |
|
| 42 |
**Methods**:
|
| 43 |
+
- `async add_loop(loop_id: str, query: str) -> ResearchLoop`: Add a new research loop to manage
|
| 44 |
+
- `async run_loops_parallel(loop_configs: list[dict], loop_func: Callable, judge_handler: Any | None = None, budget_tracker: Any | None = None) -> list[Any]`: Run multiple research loops in parallel. Takes configuration dicts and a loop function.
|
| 45 |
+
- `async update_loop_status(loop_id: str, status: LoopStatus, error: str | None = None)`: Update loop status
|
| 46 |
+
- `async sync_loop_evidence_to_state(loop_id: str)`: Synchronize evidence from a specific loop to global state
|
| 47 |
|
| 48 |
**Features**:
|
| 49 |
- Uses `asyncio.gather()` for parallel execution
|
|
|
|
| 56 |
from src.middleware.workflow_manager import WorkflowManager
|
| 57 |
|
| 58 |
manager = WorkflowManager()
|
| 59 |
+
await manager.add_loop("loop1", "Research query 1")
|
| 60 |
+
await manager.add_loop("loop2", "Research query 2")
|
| 61 |
+
|
| 62 |
+
async def run_research(config: dict) -> str:
|
| 63 |
+
loop_id = config["loop_id"]
|
| 64 |
+
query = config["query"]
|
| 65 |
+
# ... research logic ...
|
| 66 |
+
return "report"
|
| 67 |
+
|
| 68 |
+
results = await manager.run_loops_parallel(
|
| 69 |
+
loop_configs=[
|
| 70 |
+
{"loop_id": "loop1", "query": "Research query 1"},
|
| 71 |
+
{"loop_id": "loop2", "query": "Research query 2"},
|
| 72 |
+
],
|
| 73 |
+
loop_func=run_research,
|
| 74 |
+
)
|
| 75 |
```
|
| 76 |
|
| 77 |
## Budget Tracker
|
|
|
|
| 86 |
- **Iterations**: Number of iterations
|
| 87 |
|
| 88 |
**Methods**:
|
| 89 |
+
- `create_budget(loop_id: str, tokens_limit: int = 100000, time_limit_seconds: float = 600.0, iterations_limit: int = 10) -> BudgetStatus`: Create a budget for a specific loop
|
| 90 |
+
- `add_tokens(loop_id: str, tokens: int)`: Add token usage to a loop's budget
|
| 91 |
+
- `start_timer(loop_id: str)`: Start time tracking for a loop
|
| 92 |
+
- `update_timer(loop_id: str)`: Update elapsed time for a loop
|
| 93 |
+
- `increment_iteration(loop_id: str)`: Increment iteration count for a loop
|
| 94 |
+
- `check_budget(loop_id: str) -> tuple[bool, str]`: Check if a loop's budget has been exceeded. Returns (exceeded: bool, reason: str)
|
| 95 |
+
- `can_continue(loop_id: str) -> bool`: Check if a loop can continue based on budget
|
| 96 |
|
| 97 |
**Token Estimation**:
|
| 98 |
- `estimate_tokens(text: str) -> int`: ~4 chars per token
|
|
|
|
| 104 |
|
| 105 |
tracker = BudgetTracker()
|
| 106 |
budget = tracker.create_budget(
|
| 107 |
+
loop_id="research_loop",
|
| 108 |
+
tokens_limit=100000,
|
| 109 |
time_limit_seconds=600,
|
| 110 |
iterations_limit=10
|
| 111 |
)
|
| 112 |
+
tracker.start_timer("research_loop")
|
| 113 |
# ... research operations ...
|
| 114 |
+
tracker.add_tokens("research_loop", 5000)
|
| 115 |
+
tracker.update_timer("research_loop")
|
| 116 |
+
exceeded, reason = tracker.check_budget("research_loop")
|
| 117 |
+
if exceeded:
|
| 118 |
+
# Budget exceeded, stop research
|
| 119 |
+
pass
|
| 120 |
+
if not tracker.can_continue("research_loop"):
|
| 121 |
# Budget exceeded, stop research
|
| 122 |
pass
|
| 123 |
```
|
docs/architecture/orchestrators.md
CHANGED
|
@@ -25,7 +25,7 @@ DeepCritical supports multiple orchestration patterns for research workflows.
|
|
| 25 |
**Usage**:
|
| 26 |
|
| 27 |
<!--codeinclude-->
|
| 28 |
-
[IterativeResearchFlow Initialization](../src/orchestrator/research_flow.py) start_line:
|
| 29 |
<!--/codeinclude-->
|
| 30 |
|
| 31 |
### DeepResearchFlow
|
|
@@ -48,7 +48,7 @@ DeepCritical supports multiple orchestration patterns for research workflows.
|
|
| 48 |
**Usage**:
|
| 49 |
|
| 50 |
<!--codeinclude-->
|
| 51 |
-
[DeepResearchFlow Initialization](../src/orchestrator/research_flow.py) start_line:
|
| 52 |
<!--/codeinclude-->
|
| 53 |
|
| 54 |
## Graph Orchestrator
|
|
@@ -58,9 +58,10 @@ DeepCritical supports multiple orchestration patterns for research workflows.
|
|
| 58 |
**Purpose**: Graph-based execution using Pydantic AI agents as nodes
|
| 59 |
|
| 60 |
**Features**:
|
| 61 |
-
- Uses
|
| 62 |
- Routes based on research mode (iterative/deep/auto)
|
| 63 |
- Streams `AgentEvent` objects for UI
|
|
|
|
| 64 |
|
| 65 |
**Node Types**:
|
| 66 |
- **Agent Nodes**: Execute Pydantic AI agents
|
|
@@ -73,6 +74,22 @@ DeepCritical supports multiple orchestration patterns for research workflows.
|
|
| 73 |
- **Conditional Edges**: Traversed based on condition
|
| 74 |
- **Parallel Edges**: Used for parallel execution branches
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
## Orchestrator Factory
|
| 77 |
|
| 78 |
**File**: `src/orchestrator_factory.py`
|
|
@@ -99,14 +116,26 @@ DeepCritical supports multiple orchestration patterns for research workflows.
|
|
| 99 |
**Features**:
|
| 100 |
- Uses `agent-framework-core`
|
| 101 |
- ChatAgent pattern with internal LLMs per agent
|
| 102 |
-
- `MagenticBuilder` with participants:
|
| 103 |
-
-
|
| 104 |
-
-
|
| 105 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
|
| 107 |
**Requirements**:
|
| 108 |
- `agent-framework-core` package
|
| 109 |
-
- OpenAI API key
|
| 110 |
|
| 111 |
## Hierarchical Orchestrator
|
| 112 |
|
|
@@ -136,7 +165,7 @@ DeepCritical supports multiple orchestration patterns for research workflows.
|
|
| 136 |
All orchestrators must initialize workflow state:
|
| 137 |
|
| 138 |
<!--codeinclude-->
|
| 139 |
-
[Initialize Workflow State](../src/middleware/state_machine.py) start_line:98 end_line:
|
| 140 |
<!--/codeinclude-->
|
| 141 |
|
| 142 |
## Event Streaming
|
|
@@ -145,17 +174,23 @@ All orchestrators yield `AgentEvent` objects:
|
|
| 145 |
|
| 146 |
**Event Types**:
|
| 147 |
- `started`: Research started
|
|
|
|
| 148 |
- `search_complete`: Search completed
|
|
|
|
| 149 |
- `judge_complete`: Evidence evaluation completed
|
|
|
|
| 150 |
- `hypothesizing`: Generating hypotheses
|
|
|
|
|
|
|
| 151 |
- `synthesizing`: Synthesizing results
|
| 152 |
- `complete`: Research completed
|
| 153 |
- `error`: Error occurred
|
|
|
|
| 154 |
|
| 155 |
**Event Structure**:
|
| 156 |
|
| 157 |
<!--codeinclude-->
|
| 158 |
-
[AgentEvent Model](../src/utils/models.py) start_line:104 end_line:
|
| 159 |
<!--/codeinclude-->
|
| 160 |
|
| 161 |
## See Also
|
|
|
|
| 25 |
**Usage**:
|
| 26 |
|
| 27 |
<!--codeinclude-->
|
| 28 |
+
[IterativeResearchFlow Initialization](../src/orchestrator/research_flow.py) start_line:57 end_line:80
|
| 29 |
<!--/codeinclude-->
|
| 30 |
|
| 31 |
### DeepResearchFlow
|
|
|
|
| 48 |
**Usage**:
|
| 49 |
|
| 50 |
<!--codeinclude-->
|
| 51 |
+
[DeepResearchFlow Initialization](../src/orchestrator/research_flow.py) start_line:709 end_line:728
|
| 52 |
<!--/codeinclude-->
|
| 53 |
|
| 54 |
## Graph Orchestrator
|
|
|
|
| 58 |
**Purpose**: Graph-based execution using Pydantic AI agents as nodes
|
| 59 |
|
| 60 |
**Features**:
|
| 61 |
+
- Uses graph execution (`use_graph=True`) or agent chains (`use_graph=False`) as fallback
|
| 62 |
- Routes based on research mode (iterative/deep/auto)
|
| 63 |
- Streams `AgentEvent` objects for UI
|
| 64 |
+
- Uses `GraphExecutionContext` to manage execution state
|
| 65 |
|
| 66 |
**Node Types**:
|
| 67 |
- **Agent Nodes**: Execute Pydantic AI agents
|
|
|
|
| 74 |
- **Conditional Edges**: Traversed based on condition
|
| 75 |
- **Parallel Edges**: Used for parallel execution branches
|
| 76 |
|
| 77 |
+
**Special Node Handling**:
|
| 78 |
+
|
| 79 |
+
The `GraphOrchestrator` has special handling for certain nodes:
|
| 80 |
+
|
| 81 |
+
- **`execute_tools` node**: State node that uses `search_handler` to execute searches and add evidence to workflow state
|
| 82 |
+
- **`parallel_loops` node**: Parallel node that executes `IterativeResearchFlow` instances for each section in deep research mode
|
| 83 |
+
- **`synthesizer` node**: Agent node that calls `LongWriterAgent.write_report()` directly with `ReportDraft` instead of using `agent.run()`
|
| 84 |
+
- **`writer` node**: Agent node that calls `WriterAgent.write_report()` directly with findings instead of using `agent.run()`
|
| 85 |
+
|
| 86 |
+
**GraphExecutionContext**:
|
| 87 |
+
|
| 88 |
+
The orchestrator uses `GraphExecutionContext` to manage execution state:
|
| 89 |
+
- Tracks current node, visited nodes, and node results
|
| 90 |
+
- Manages workflow state and budget tracker
|
| 91 |
+
- Provides methods to store and retrieve node execution results
|
| 92 |
+
|
| 93 |
## Orchestrator Factory
|
| 94 |
|
| 95 |
**File**: `src/orchestrator_factory.py`
|
|
|
|
| 116 |
**Features**:
|
| 117 |
- Uses `agent-framework-core`
|
| 118 |
- ChatAgent pattern with internal LLMs per agent
|
| 119 |
+
- `MagenticBuilder` with participants:
|
| 120 |
+
- `searcher`: SearchAgent (wraps SearchHandler)
|
| 121 |
+
- `hypothesizer`: HypothesisAgent (generates hypotheses)
|
| 122 |
+
- `judge`: JudgeAgent (evaluates evidence)
|
| 123 |
+
- `reporter`: ReportAgent (generates final report)
|
| 124 |
+
- Manager orchestrates agents via chat client (OpenAI or HuggingFace)
|
| 125 |
+
- Event-driven: converts Magentic events to `AgentEvent` for UI streaming via `_process_event()` method
|
| 126 |
+
- Supports max rounds, stall detection, and reset handling
|
| 127 |
+
|
| 128 |
+
**Event Processing**:
|
| 129 |
+
|
| 130 |
+
The orchestrator processes Magentic events and converts them to `AgentEvent`:
|
| 131 |
+
- `MagenticOrchestratorMessageEvent` → `AgentEvent` with type based on message content
|
| 132 |
+
- `MagenticAgentMessageEvent` → `AgentEvent` with type based on agent name
|
| 133 |
+
- `MagenticAgentDeltaEvent` → `AgentEvent` for streaming updates
|
| 134 |
+
- `MagenticFinalResultEvent` → `AgentEvent` with type "complete"
|
| 135 |
|
| 136 |
**Requirements**:
|
| 137 |
- `agent-framework-core` package
|
| 138 |
+
- OpenAI API key or HuggingFace authentication
|
| 139 |
|
| 140 |
## Hierarchical Orchestrator
|
| 141 |
|
|
|
|
| 165 |
All orchestrators must initialize workflow state:
|
| 166 |
|
| 167 |
<!--codeinclude-->
|
| 168 |
+
[Initialize Workflow State](../src/middleware/state_machine.py) start_line:98 end_line:112
|
| 169 |
<!--/codeinclude-->
|
| 170 |
|
| 171 |
## Event Streaming
|
|
|
|
| 174 |
|
| 175 |
**Event Types**:
|
| 176 |
- `started`: Research started
|
| 177 |
+
- `searching`: Search in progress
|
| 178 |
- `search_complete`: Search completed
|
| 179 |
+
- `judging`: Evidence evaluation in progress
|
| 180 |
- `judge_complete`: Evidence evaluation completed
|
| 181 |
+
- `looping`: Iteration in progress
|
| 182 |
- `hypothesizing`: Generating hypotheses
|
| 183 |
+
- `analyzing`: Statistical analysis in progress
|
| 184 |
+
- `analysis_complete`: Statistical analysis completed
|
| 185 |
- `synthesizing`: Synthesizing results
|
| 186 |
- `complete`: Research completed
|
| 187 |
- `error`: Error occurred
|
| 188 |
+
- `streaming`: Streaming update (delta events)
|
| 189 |
|
| 190 |
**Event Structure**:
|
| 191 |
|
| 192 |
<!--codeinclude-->
|
| 193 |
+
[AgentEvent Model](../src/utils/models.py) start_line:104 end_line:126
|
| 194 |
<!--/codeinclude-->
|
| 195 |
|
| 196 |
## See Also
|
docs/architecture/services.md
CHANGED
|
@@ -10,17 +10,18 @@ DeepCritical provides several services for embeddings, RAG, and statistical anal
|
|
| 10 |
|
| 11 |
**Features**:
|
| 12 |
- **No API Key Required**: Uses local sentence-transformers models
|
| 13 |
-
- **Async-Safe**: All operations use `run_in_executor()` to avoid blocking
|
| 14 |
-
- **ChromaDB Storage**:
|
| 15 |
-
- **Deduplication**: 0.
|
| 16 |
|
| 17 |
**Model**: Configurable via `settings.local_embedding_model` (default: `all-MiniLM-L6-v2`)
|
| 18 |
|
| 19 |
**Methods**:
|
| 20 |
-
- `async def embed(text: str) -> list[float]`: Generate embeddings
|
| 21 |
-
- `async def embed_batch(texts: list[str]) -> list[list[float]]`: Batch embedding
|
| 22 |
-
- `async def
|
| 23 |
-
- `async def
|
|
|
|
| 24 |
|
| 25 |
**Usage**:
|
| 26 |
```python
|
|
@@ -32,15 +33,21 @@ embedding = await service.embed("text to embed")
|
|
| 32 |
|
| 33 |
## LlamaIndex RAG Service
|
| 34 |
|
| 35 |
-
**File**: `src/services/
|
| 36 |
|
| 37 |
**Purpose**: Retrieval-Augmented Generation using LlamaIndex
|
| 38 |
|
| 39 |
**Features**:
|
| 40 |
-
- **
|
| 41 |
-
- **
|
|
|
|
| 42 |
- **Metadata Preservation**: Preserves source, title, URL, date, authors
|
| 43 |
-
- **Lazy Initialization**: Graceful fallback if
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
**Methods**:
|
| 46 |
- `async def ingest_evidence(evidence: list[Evidence]) -> None`: Ingest evidence into RAG
|
|
@@ -49,9 +56,13 @@ embedding = await service.embed("text to embed")
|
|
| 49 |
|
| 50 |
**Usage**:
|
| 51 |
```python
|
| 52 |
-
from src.services.
|
| 53 |
|
| 54 |
-
service = get_rag_service(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
if service:
|
| 56 |
documents = await service.retrieve("query", top_k=5)
|
| 57 |
```
|
|
@@ -92,13 +103,19 @@ result = await analyzer.analyze(
|
|
| 92 |
|
| 93 |
## Singleton Pattern
|
| 94 |
|
| 95 |
-
|
| 96 |
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
|
| 103 |
This ensures:
|
| 104 |
- Single instance per process
|
|
|
|
| 10 |
|
| 11 |
**Features**:
|
| 12 |
- **No API Key Required**: Uses local sentence-transformers models
|
| 13 |
+
- **Async-Safe**: All operations use `run_in_executor()` to avoid blocking the event loop
|
| 14 |
+
- **ChromaDB Storage**: In-memory vector storage for embeddings
|
| 15 |
+
- **Deduplication**: 0.9 similarity threshold by default (90% similarity = duplicate, configurable)
|
| 16 |
|
| 17 |
**Model**: Configurable via `settings.local_embedding_model` (default: `all-MiniLM-L6-v2`)
|
| 18 |
|
| 19 |
**Methods**:
|
| 20 |
+
- `async def embed(text: str) -> list[float]`: Generate embeddings (async-safe via `run_in_executor()`)
|
| 21 |
+
- `async def embed_batch(texts: list[str]) -> list[list[float]]`: Batch embedding (more efficient)
|
| 22 |
+
- `async def add_evidence(evidence_id: str, content: str, metadata: dict[str, Any]) -> None`: Add evidence to vector store
|
| 23 |
+
- `async def search_similar(query: str, n_results: int = 5) -> list[dict[str, Any]]`: Find semantically similar evidence
|
| 24 |
+
- `async def deduplicate(new_evidence: list[Evidence], threshold: float = 0.9) -> list[Evidence]`: Remove semantically duplicate evidence
|
| 25 |
|
| 26 |
**Usage**:
|
| 27 |
```python
|
|
|
|
| 33 |
|
| 34 |
## LlamaIndex RAG Service
|
| 35 |
|
| 36 |
+
**File**: `src/services/llamaindex_rag.py`
|
| 37 |
|
| 38 |
**Purpose**: Retrieval-Augmented Generation using LlamaIndex
|
| 39 |
|
| 40 |
**Features**:
|
| 41 |
+
- **Multiple Embedding Providers**: OpenAI embeddings (requires `OPENAI_API_KEY`) or local sentence-transformers (no API key)
|
| 42 |
+
- **Multiple LLM Providers**: HuggingFace LLM (preferred) or OpenAI LLM (fallback) for query synthesis
|
| 43 |
+
- **ChromaDB Storage**: Vector database for document storage (supports in-memory mode)
|
| 44 |
- **Metadata Preservation**: Preserves source, title, URL, date, authors
|
| 45 |
+
- **Lazy Initialization**: Graceful fallback if dependencies not available
|
| 46 |
+
|
| 47 |
+
**Initialization Parameters**:
|
| 48 |
+
- `use_openai_embeddings: bool | None`: Force OpenAI embeddings (None = auto-detect)
|
| 49 |
+
- `use_in_memory: bool`: Use in-memory ChromaDB client (useful for tests)
|
| 50 |
+
- `oauth_token: str | None`: Optional OAuth token from HuggingFace login (takes priority over env vars)
|
| 51 |
|
| 52 |
**Methods**:
|
| 53 |
- `async def ingest_evidence(evidence: list[Evidence]) -> None`: Ingest evidence into RAG
|
|
|
|
| 56 |
|
| 57 |
**Usage**:
|
| 58 |
```python
|
| 59 |
+
from src.services.llamaindex_rag import get_rag_service
|
| 60 |
|
| 61 |
+
service = get_rag_service(
|
| 62 |
+
use_openai_embeddings=False, # Use local embeddings
|
| 63 |
+
use_in_memory=True, # Use in-memory ChromaDB
|
| 64 |
+
oauth_token=token # Optional HuggingFace token
|
| 65 |
+
)
|
| 66 |
if service:
|
| 67 |
documents = await service.retrieve("query", top_k=5)
|
| 68 |
```
|
|
|
|
| 103 |
|
| 104 |
## Singleton Pattern
|
| 105 |
|
| 106 |
+
Services use singleton patterns for lazy initialization:
|
| 107 |
|
| 108 |
+
**EmbeddingService**: Uses a global variable pattern:
|
| 109 |
+
|
| 110 |
+
<!--codeinclude-->
|
| 111 |
+
[EmbeddingService Singleton](../src/services/embeddings.py) start_line:164 end_line:172
|
| 112 |
+
<!--/codeinclude-->
|
| 113 |
+
|
| 114 |
+
**LlamaIndexRAGService**: Direct instantiation (no caching):
|
| 115 |
+
|
| 116 |
+
<!--codeinclude-->
|
| 117 |
+
[LlamaIndexRAGService Factory](../src/services/llamaindex_rag.py) start_line:440 end_line:466
|
| 118 |
+
<!--/codeinclude-->
|
| 119 |
|
| 120 |
This ensures:
|
| 121 |
- Single instance per process
|
docs/architecture/tools.md
CHANGED
|
@@ -14,14 +14,9 @@ All tools implement the `SearchTool` protocol from `src/tools/base.py`:
|
|
| 14 |
|
| 15 |
All tools use the `@retry` decorator from tenacity:
|
| 16 |
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
wait=wait_exponential(...)
|
| 21 |
-
)
|
| 22 |
-
async def search(self, query: str, max_results: int = 10) -> list[Evidence]:
|
| 23 |
-
# Implementation
|
| 24 |
-
```
|
| 25 |
|
| 26 |
Tools with API rate limits implement `_rate_limit()` method and use shared rate limiters from `src/tools/rate_limiter.py`.
|
| 27 |
|
|
@@ -122,11 +117,23 @@ Missing fields are handled gracefully with defaults.
|
|
| 122 |
|
| 123 |
**Purpose**: Orchestrates parallel searches across multiple tools
|
| 124 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
**Features**:
|
| 126 |
-
- Uses `asyncio.gather()` with `return_exceptions=True`
|
| 127 |
-
- Aggregates results into `SearchResult`
|
| 128 |
-
- Handles tool failures gracefully
|
| 129 |
- Deduplicates results by URL
|
|
|
|
|
|
|
| 130 |
|
| 131 |
## Tool Registration
|
| 132 |
|
|
@@ -136,14 +143,21 @@ Tools are registered in the search handler:
|
|
| 136 |
from src.tools.pubmed import PubMedTool
|
| 137 |
from src.tools.clinicaltrials import ClinicalTrialsTool
|
| 138 |
from src.tools.europepmc import EuropePMCTool
|
|
|
|
| 139 |
|
| 140 |
search_handler = SearchHandler(
|
| 141 |
tools=[
|
| 142 |
PubMedTool(),
|
| 143 |
ClinicalTrialsTool(),
|
| 144 |
EuropePMCTool(),
|
| 145 |
-
]
|
|
|
|
|
|
|
|
|
|
| 146 |
)
|
|
|
|
|
|
|
|
|
|
| 147 |
```
|
| 148 |
|
| 149 |
## See Also
|
|
|
|
| 14 |
|
| 15 |
All tools use the `@retry` decorator from tenacity:
|
| 16 |
|
| 17 |
+
<!--codeinclude-->
|
| 18 |
+
[Retry Decorator Pattern](../src/tools/pubmed.py) start_line:46 end_line:50
|
| 19 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
Tools with API rate limits implement `_rate_limit()` method and use shared rate limiters from `src/tools/rate_limiter.py`.
|
| 22 |
|
|
|
|
| 117 |
|
| 118 |
**Purpose**: Orchestrates parallel searches across multiple tools
|
| 119 |
|
| 120 |
+
**Initialization Parameters**:
|
| 121 |
+
- `tools: list[SearchTool]`: List of search tools to use
|
| 122 |
+
- `timeout: float = 30.0`: Timeout for each search in seconds
|
| 123 |
+
- `include_rag: bool = False`: Whether to include RAG tool in searches
|
| 124 |
+
- `auto_ingest_to_rag: bool = True`: Whether to automatically ingest results into RAG
|
| 125 |
+
- `oauth_token: str | None = None`: Optional OAuth token from HuggingFace login (for RAG LLM)
|
| 126 |
+
|
| 127 |
+
**Methods**:
|
| 128 |
+
- `async def execute(query: str, max_results_per_tool: int = 10) -> SearchResult`: Execute search across all tools in parallel
|
| 129 |
+
|
| 130 |
**Features**:
|
| 131 |
+
- Uses `asyncio.gather()` with `return_exceptions=True` for parallel execution
|
| 132 |
+
- Aggregates results into `SearchResult` with evidence and metadata
|
| 133 |
+
- Handles tool failures gracefully (continues with other tools)
|
| 134 |
- Deduplicates results by URL
|
| 135 |
+
- Automatically ingests results into RAG if `auto_ingest_to_rag=True`
|
| 136 |
+
- Can add RAG tool dynamically via `add_rag_tool()` method
|
| 137 |
|
| 138 |
## Tool Registration
|
| 139 |
|
|
|
|
| 143 |
from src.tools.pubmed import PubMedTool
|
| 144 |
from src.tools.clinicaltrials import ClinicalTrialsTool
|
| 145 |
from src.tools.europepmc import EuropePMCTool
|
| 146 |
+
from src.tools.search_handler import SearchHandler
|
| 147 |
|
| 148 |
search_handler = SearchHandler(
|
| 149 |
tools=[
|
| 150 |
PubMedTool(),
|
| 151 |
ClinicalTrialsTool(),
|
| 152 |
EuropePMCTool(),
|
| 153 |
+
],
|
| 154 |
+
include_rag=True, # Include RAG tool for semantic search
|
| 155 |
+
auto_ingest_to_rag=True, # Automatically ingest results into RAG
|
| 156 |
+
oauth_token=token # Optional HuggingFace token for RAG LLM
|
| 157 |
)
|
| 158 |
+
|
| 159 |
+
# Execute search
|
| 160 |
+
result = await search_handler.execute("query", max_results_per_tool=10)
|
| 161 |
```
|
| 162 |
|
| 163 |
## See Also
|
docs/architecture/workflow-diagrams.md
CHANGED
|
@@ -627,23 +627,10 @@ gantt
|
|
| 627 |
## Implementation Highlights
|
| 628 |
|
| 629 |
**Simple 4-Agent Setup:**
|
| 630 |
-
|
| 631 |
-
|
| 632 |
-
|
| 633 |
-
|
| 634 |
-
hypothesis=HypothesisAgent(tools=[background_tool]),
|
| 635 |
-
search=SearchAgent(tools=[web_search, rag_tool]),
|
| 636 |
-
analysis=AnalysisAgent(tools=[code_execution]),
|
| 637 |
-
report=ReportAgent(tools=[code_execution, visualization])
|
| 638 |
-
)
|
| 639 |
-
.with_standard_manager(
|
| 640 |
-
chat_client=AnthropicClient(model="claude-sonnet-4"),
|
| 641 |
-
max_round_count=15, # Prevent infinite loops
|
| 642 |
-
max_stall_count=3 # Detect stuck workflows
|
| 643 |
-
)
|
| 644 |
-
.build()
|
| 645 |
-
)
|
| 646 |
-
```
|
| 647 |
|
| 648 |
**Manager handles quality assessment in its instructions:**
|
| 649 |
- Checks hypothesis quality (testable, novel, clear)
|
|
|
|
| 627 |
## Implementation Highlights
|
| 628 |
|
| 629 |
**Simple 4-Agent Setup:**
|
| 630 |
+
|
| 631 |
+
<!--codeinclude-->
|
| 632 |
+
[Magentic Workflow Builder](../src/orchestrator_magentic.py) start_line:72 end_line:99
|
| 633 |
+
<!--/codeinclude-->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 634 |
|
| 635 |
**Manager handles quality assessment in its instructions:**
|
| 636 |
- Checks hypothesis quality (testable, novel, clear)
|
docs/configuration/CONFIGURATION.md
DELETED
|
@@ -1,557 +0,0 @@
|
|
| 1 |
-
# Configuration Guide
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
DeepCritical uses **Pydantic Settings** for centralized configuration management. All settings are defined in the `Settings` class in `src/utils/config.py` and can be configured via environment variables or a `.env` file.
|
| 6 |
-
|
| 7 |
-
The configuration system provides:
|
| 8 |
-
|
| 9 |
-
- **Type Safety**: Strongly-typed fields with Pydantic validation
|
| 10 |
-
- **Environment File Support**: Automatically loads from `.env` file (if present)
|
| 11 |
-
- **Case-Insensitive**: Environment variables are case-insensitive
|
| 12 |
-
- **Singleton Pattern**: Global `settings` instance for easy access throughout the codebase
|
| 13 |
-
- **Validation**: Automatic validation on load with helpful error messages
|
| 14 |
-
|
| 15 |
-
## Quick Start
|
| 16 |
-
|
| 17 |
-
1. Create a `.env` file in the project root
|
| 18 |
-
2. Set at least one LLM API key (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `HF_TOKEN`)
|
| 19 |
-
3. Optionally configure other services as needed
|
| 20 |
-
4. The application will automatically load and validate your configuration
|
| 21 |
-
|
| 22 |
-
## Configuration System Architecture
|
| 23 |
-
|
| 24 |
-
### Settings Class
|
| 25 |
-
|
| 26 |
-
The `Settings` class extends `BaseSettings` from `pydantic_settings` and defines all application configuration:
|
| 27 |
-
|
| 28 |
-
<!--codeinclude-->
|
| 29 |
-
[Settings Class Definition](../src/utils/config.py) start_line:13 end_line:21
|
| 30 |
-
<!--/codeinclude-->
|
| 31 |
-
|
| 32 |
-
### Singleton Instance
|
| 33 |
-
|
| 34 |
-
A global `settings` instance is available for import:
|
| 35 |
-
|
| 36 |
-
<!--codeinclude-->
|
| 37 |
-
[Singleton Instance](../src/utils/config.py) start_line:234 end_line:235
|
| 38 |
-
<!--/codeinclude-->
|
| 39 |
-
|
| 40 |
-
### Usage Pattern
|
| 41 |
-
|
| 42 |
-
Access configuration throughout the codebase:
|
| 43 |
-
|
| 44 |
-
```python
|
| 45 |
-
from src.utils.config import settings
|
| 46 |
-
|
| 47 |
-
# Check if API keys are available
|
| 48 |
-
if settings.has_openai_key:
|
| 49 |
-
# Use OpenAI
|
| 50 |
-
pass
|
| 51 |
-
|
| 52 |
-
# Access configuration values
|
| 53 |
-
max_iterations = settings.max_iterations
|
| 54 |
-
web_search_provider = settings.web_search_provider
|
| 55 |
-
```
|
| 56 |
-
|
| 57 |
-
## Required Configuration
|
| 58 |
-
|
| 59 |
-
### LLM Provider
|
| 60 |
-
|
| 61 |
-
You must configure at least one LLM provider. The system supports:
|
| 62 |
-
|
| 63 |
-
- **OpenAI**: Requires `OPENAI_API_KEY`
|
| 64 |
-
- **Anthropic**: Requires `ANTHROPIC_API_KEY`
|
| 65 |
-
- **HuggingFace**: Optional `HF_TOKEN` or `HUGGINGFACE_API_KEY` (can work without key for public models)
|
| 66 |
-
|
| 67 |
-
#### OpenAI Configuration
|
| 68 |
-
|
| 69 |
-
```bash
|
| 70 |
-
LLM_PROVIDER=openai
|
| 71 |
-
OPENAI_API_KEY=your_openai_api_key_here
|
| 72 |
-
OPENAI_MODEL=gpt-5.1
|
| 73 |
-
```
|
| 74 |
-
|
| 75 |
-
The default model is defined in the `Settings` class:
|
| 76 |
-
|
| 77 |
-
<!--codeinclude-->
|
| 78 |
-
[OpenAI Model Configuration](../src/utils/config.py) start_line:29 end_line:29
|
| 79 |
-
<!--/codeinclude-->
|
| 80 |
-
|
| 81 |
-
#### Anthropic Configuration
|
| 82 |
-
|
| 83 |
-
```bash
|
| 84 |
-
LLM_PROVIDER=anthropic
|
| 85 |
-
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
| 86 |
-
ANTHROPIC_MODEL=claude-sonnet-4-5-20250929
|
| 87 |
-
```
|
| 88 |
-
|
| 89 |
-
The default model is defined in the `Settings` class:
|
| 90 |
-
|
| 91 |
-
<!--codeinclude-->
|
| 92 |
-
[Anthropic Model Configuration](../src/utils/config.py) start_line:30 end_line:32
|
| 93 |
-
<!--/codeinclude-->
|
| 94 |
-
|
| 95 |
-
#### HuggingFace Configuration
|
| 96 |
-
|
| 97 |
-
HuggingFace can work without an API key for public models, but an API key provides higher rate limits:
|
| 98 |
-
|
| 99 |
-
```bash
|
| 100 |
-
# Option 1: Using HF_TOKEN (preferred)
|
| 101 |
-
HF_TOKEN=your_huggingface_token_here
|
| 102 |
-
|
| 103 |
-
# Option 2: Using HUGGINGFACE_API_KEY (alternative)
|
| 104 |
-
HUGGINGFACE_API_KEY=your_huggingface_api_key_here
|
| 105 |
-
|
| 106 |
-
# Default model
|
| 107 |
-
HUGGINGFACE_MODEL=meta-llama/Llama-3.1-8B-Instruct
|
| 108 |
-
```
|
| 109 |
-
|
| 110 |
-
The HuggingFace token can be set via either environment variable:
|
| 111 |
-
|
| 112 |
-
<!--codeinclude-->
|
| 113 |
-
[HuggingFace Token Configuration](../src/utils/config.py) start_line:33 end_line:35
|
| 114 |
-
<!--/codeinclude-->
|
| 115 |
-
|
| 116 |
-
<!--codeinclude-->
|
| 117 |
-
[HuggingFace API Key Configuration](../src/utils/config.py) start_line:57 end_line:59
|
| 118 |
-
<!--/codeinclude-->
|
| 119 |
-
|
| 120 |
-
## Optional Configuration
|
| 121 |
-
|
| 122 |
-
### Embedding Configuration
|
| 123 |
-
|
| 124 |
-
DeepCritical supports multiple embedding providers for semantic search and RAG:
|
| 125 |
-
|
| 126 |
-
```bash
|
| 127 |
-
# Embedding Provider: "openai", "local", or "huggingface"
|
| 128 |
-
EMBEDDING_PROVIDER=local
|
| 129 |
-
|
| 130 |
-
# OpenAI Embedding Model (used by LlamaIndex RAG)
|
| 131 |
-
OPENAI_EMBEDDING_MODEL=text-embedding-3-small
|
| 132 |
-
|
| 133 |
-
# Local Embedding Model (sentence-transformers, used by EmbeddingService)
|
| 134 |
-
LOCAL_EMBEDDING_MODEL=all-MiniLM-L6-v2
|
| 135 |
-
|
| 136 |
-
# HuggingFace Embedding Model
|
| 137 |
-
HUGGINGFACE_EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
|
| 138 |
-
```
|
| 139 |
-
|
| 140 |
-
The embedding provider configuration:
|
| 141 |
-
|
| 142 |
-
<!--codeinclude-->
|
| 143 |
-
[Embedding Provider Configuration](../src/utils/config.py) start_line:47 end_line:50
|
| 144 |
-
<!--/codeinclude-->
|
| 145 |
-
|
| 146 |
-
**Note**: OpenAI embeddings require `OPENAI_API_KEY`. The local provider (default) uses sentence-transformers and requires no API key.
|
| 147 |
-
|
| 148 |
-
### Web Search Configuration
|
| 149 |
-
|
| 150 |
-
DeepCritical supports multiple web search providers:
|
| 151 |
-
|
| 152 |
-
```bash
|
| 153 |
-
# Web Search Provider: "serper", "searchxng", "brave", "tavily", or "duckduckgo"
|
| 154 |
-
# Default: "duckduckgo" (no API key required)
|
| 155 |
-
WEB_SEARCH_PROVIDER=duckduckgo
|
| 156 |
-
|
| 157 |
-
# Serper API Key (for Google search via Serper)
|
| 158 |
-
SERPER_API_KEY=your_serper_api_key_here
|
| 159 |
-
|
| 160 |
-
# SearchXNG Host URL (for self-hosted search)
|
| 161 |
-
SEARCHXNG_HOST=http://localhost:8080
|
| 162 |
-
|
| 163 |
-
# Brave Search API Key
|
| 164 |
-
BRAVE_API_KEY=your_brave_api_key_here
|
| 165 |
-
|
| 166 |
-
# Tavily API Key
|
| 167 |
-
TAVILY_API_KEY=your_tavily_api_key_here
|
| 168 |
-
```
|
| 169 |
-
|
| 170 |
-
The web search provider configuration:
|
| 171 |
-
|
| 172 |
-
<!--codeinclude-->
|
| 173 |
-
[Web Search Provider Configuration](../src/utils/config.py) start_line:71 end_line:74
|
| 174 |
-
<!--/codeinclude-->
|
| 175 |
-
|
| 176 |
-
**Note**: DuckDuckGo is the default and requires no API key, making it ideal for development and testing.
|
| 177 |
-
|
| 178 |
-
### PubMed Configuration
|
| 179 |
-
|
| 180 |
-
PubMed search supports optional NCBI API key for higher rate limits:
|
| 181 |
-
|
| 182 |
-
```bash
|
| 183 |
-
# NCBI API Key (optional, for higher rate limits: 10 req/sec vs 3 req/sec)
|
| 184 |
-
NCBI_API_KEY=your_ncbi_api_key_here
|
| 185 |
-
```
|
| 186 |
-
|
| 187 |
-
The PubMed tool uses this configuration:
|
| 188 |
-
|
| 189 |
-
<!--codeinclude-->
|
| 190 |
-
[PubMed Tool Configuration](../src/tools/pubmed.py) start_line:22 end_line:29
|
| 191 |
-
<!--/codeinclude-->
|
| 192 |
-
|
| 193 |
-
### Agent Configuration
|
| 194 |
-
|
| 195 |
-
Control agent behavior and research loop execution:
|
| 196 |
-
|
| 197 |
-
```bash
|
| 198 |
-
# Maximum iterations per research loop (1-50, default: 10)
|
| 199 |
-
MAX_ITERATIONS=10
|
| 200 |
-
|
| 201 |
-
# Search timeout in seconds
|
| 202 |
-
SEARCH_TIMEOUT=30
|
| 203 |
-
|
| 204 |
-
# Use graph-based execution for research flows
|
| 205 |
-
USE_GRAPH_EXECUTION=false
|
| 206 |
-
```
|
| 207 |
-
|
| 208 |
-
The agent configuration fields:
|
| 209 |
-
|
| 210 |
-
<!--codeinclude-->
|
| 211 |
-
[Agent Configuration](../src/utils/config.py) start_line:80 end_line:85
|
| 212 |
-
<!--/codeinclude-->
|
| 213 |
-
|
| 214 |
-
### Budget & Rate Limiting Configuration
|
| 215 |
-
|
| 216 |
-
Control resource limits for research loops:
|
| 217 |
-
|
| 218 |
-
```bash
|
| 219 |
-
# Default token budget per research loop (1000-1000000, default: 100000)
|
| 220 |
-
DEFAULT_TOKEN_LIMIT=100000
|
| 221 |
-
|
| 222 |
-
# Default time limit per research loop in minutes (1-120, default: 10)
|
| 223 |
-
DEFAULT_TIME_LIMIT_MINUTES=10
|
| 224 |
-
|
| 225 |
-
# Default iterations limit per research loop (1-50, default: 10)
|
| 226 |
-
DEFAULT_ITERATIONS_LIMIT=10
|
| 227 |
-
```
|
| 228 |
-
|
| 229 |
-
The budget configuration with validation:
|
| 230 |
-
|
| 231 |
-
<!--codeinclude-->
|
| 232 |
-
[Budget Configuration](../src/utils/config.py) start_line:87 end_line:105
|
| 233 |
-
<!--/codeinclude-->
|
| 234 |
-
|
| 235 |
-
### RAG Service Configuration
|
| 236 |
-
|
| 237 |
-
Configure the Retrieval-Augmented Generation service:
|
| 238 |
-
|
| 239 |
-
```bash
|
| 240 |
-
# ChromaDB collection name for RAG
|
| 241 |
-
RAG_COLLECTION_NAME=deepcritical_evidence
|
| 242 |
-
|
| 243 |
-
# Number of top results to retrieve from RAG (1-50, default: 5)
|
| 244 |
-
RAG_SIMILARITY_TOP_K=5
|
| 245 |
-
|
| 246 |
-
# Automatically ingest evidence into RAG
|
| 247 |
-
RAG_AUTO_INGEST=true
|
| 248 |
-
```
|
| 249 |
-
|
| 250 |
-
The RAG configuration:
|
| 251 |
-
|
| 252 |
-
<!--codeinclude-->
|
| 253 |
-
[RAG Service Configuration](../src/utils/config.py) start_line:127 end_line:141
|
| 254 |
-
<!--/codeinclude-->
|
| 255 |
-
|
| 256 |
-
### ChromaDB Configuration
|
| 257 |
-
|
| 258 |
-
Configure the vector database for embeddings and RAG:
|
| 259 |
-
|
| 260 |
-
```bash
|
| 261 |
-
# ChromaDB storage path
|
| 262 |
-
CHROMA_DB_PATH=./chroma_db
|
| 263 |
-
|
| 264 |
-
# Whether to persist ChromaDB to disk
|
| 265 |
-
CHROMA_DB_PERSIST=true
|
| 266 |
-
|
| 267 |
-
# ChromaDB server host (for remote ChromaDB, optional)
|
| 268 |
-
CHROMA_DB_HOST=localhost
|
| 269 |
-
|
| 270 |
-
# ChromaDB server port (for remote ChromaDB, optional)
|
| 271 |
-
CHROMA_DB_PORT=8000
|
| 272 |
-
```
|
| 273 |
-
|
| 274 |
-
The ChromaDB configuration:
|
| 275 |
-
|
| 276 |
-
<!--codeinclude-->
|
| 277 |
-
[ChromaDB Configuration](../src/utils/config.py) start_line:113 end_line:125
|
| 278 |
-
<!--/codeinclude-->
|
| 279 |
-
|
| 280 |
-
### External Services
|
| 281 |
-
|
| 282 |
-
#### Modal Configuration
|
| 283 |
-
|
| 284 |
-
Modal is used for secure sandbox execution of statistical analysis:
|
| 285 |
-
|
| 286 |
-
```bash
|
| 287 |
-
# Modal Token ID (for Modal sandbox execution)
|
| 288 |
-
MODAL_TOKEN_ID=your_modal_token_id_here
|
| 289 |
-
|
| 290 |
-
# Modal Token Secret
|
| 291 |
-
MODAL_TOKEN_SECRET=your_modal_token_secret_here
|
| 292 |
-
```
|
| 293 |
-
|
| 294 |
-
The Modal configuration:
|
| 295 |
-
|
| 296 |
-
<!--codeinclude-->
|
| 297 |
-
[Modal Configuration](../src/utils/config.py) start_line:110 end_line:112
|
| 298 |
-
<!--/codeinclude-->
|
| 299 |
-
|
| 300 |
-
### Logging Configuration
|
| 301 |
-
|
| 302 |
-
Configure structured logging:
|
| 303 |
-
|
| 304 |
-
```bash
|
| 305 |
-
# Log Level: "DEBUG", "INFO", "WARNING", or "ERROR"
|
| 306 |
-
LOG_LEVEL=INFO
|
| 307 |
-
```
|
| 308 |
-
|
| 309 |
-
The logging configuration:
|
| 310 |
-
|
| 311 |
-
<!--codeinclude-->
|
| 312 |
-
[Logging Configuration](../src/utils/config.py) start_line:107 end_line:108
|
| 313 |
-
<!--/codeinclude-->
|
| 314 |
-
|
| 315 |
-
Logging is configured via the `configure_logging()` function:
|
| 316 |
-
|
| 317 |
-
<!--codeinclude-->
|
| 318 |
-
[Configure Logging Function](../src/utils/config.py) start_line:212 end_line:231
|
| 319 |
-
<!--/codeinclude-->
|
| 320 |
-
|
| 321 |
-
## Configuration Properties
|
| 322 |
-
|
| 323 |
-
The `Settings` class provides helpful properties for checking configuration state:
|
| 324 |
-
|
| 325 |
-
### API Key Availability
|
| 326 |
-
|
| 327 |
-
Check which API keys are available:
|
| 328 |
-
|
| 329 |
-
<!--codeinclude-->
|
| 330 |
-
[API Key Availability Properties](../src/utils/config.py) start_line:171 end_line:189
|
| 331 |
-
<!--/codeinclude-->
|
| 332 |
-
|
| 333 |
-
**Usage:**
|
| 334 |
-
|
| 335 |
-
```python
|
| 336 |
-
from src.utils.config import settings
|
| 337 |
-
|
| 338 |
-
# Check API key availability
|
| 339 |
-
if settings.has_openai_key:
|
| 340 |
-
# Use OpenAI
|
| 341 |
-
pass
|
| 342 |
-
|
| 343 |
-
if settings.has_anthropic_key:
|
| 344 |
-
# Use Anthropic
|
| 345 |
-
pass
|
| 346 |
-
|
| 347 |
-
if settings.has_huggingface_key:
|
| 348 |
-
# Use HuggingFace
|
| 349 |
-
pass
|
| 350 |
-
|
| 351 |
-
if settings.has_any_llm_key:
|
| 352 |
-
# At least one LLM is available
|
| 353 |
-
pass
|
| 354 |
-
```
|
| 355 |
-
|
| 356 |
-
### Service Availability
|
| 357 |
-
|
| 358 |
-
Check if external services are configured:
|
| 359 |
-
|
| 360 |
-
<!--codeinclude-->
|
| 361 |
-
[Modal Availability Property](../src/utils/config.py) start_line:143 end_line:146
|
| 362 |
-
<!--/codeinclude-->
|
| 363 |
-
|
| 364 |
-
<!--codeinclude-->
|
| 365 |
-
[Web Search Availability Property](../src/utils/config.py) start_line:191 end_line:204
|
| 366 |
-
<!--/codeinclude-->
|
| 367 |
-
|
| 368 |
-
**Usage:**
|
| 369 |
-
|
| 370 |
-
```python
|
| 371 |
-
from src.utils.config import settings
|
| 372 |
-
|
| 373 |
-
# Check service availability
|
| 374 |
-
if settings.modal_available:
|
| 375 |
-
# Use Modal sandbox
|
| 376 |
-
pass
|
| 377 |
-
|
| 378 |
-
if settings.web_search_available:
|
| 379 |
-
# Web search is configured
|
| 380 |
-
pass
|
| 381 |
-
```
|
| 382 |
-
|
| 383 |
-
### API Key Retrieval
|
| 384 |
-
|
| 385 |
-
Get the API key for the configured provider:
|
| 386 |
-
|
| 387 |
-
<!--codeinclude-->
|
| 388 |
-
[Get API Key Method](../src/utils/config.py) start_line:148 end_line:160
|
| 389 |
-
<!--/codeinclude-->
|
| 390 |
-
|
| 391 |
-
For OpenAI-specific operations (e.g., Magentic mode):
|
| 392 |
-
|
| 393 |
-
<!--codeinclude-->
|
| 394 |
-
[Get OpenAI API Key Method](../src/utils/config.py) start_line:162 end_line:169
|
| 395 |
-
<!--/codeinclude-->
|
| 396 |
-
|
| 397 |
-
## Configuration Usage in Codebase
|
| 398 |
-
|
| 399 |
-
The configuration system is used throughout the codebase:
|
| 400 |
-
|
| 401 |
-
### LLM Factory
|
| 402 |
-
|
| 403 |
-
The LLM factory uses settings to create appropriate models:
|
| 404 |
-
|
| 405 |
-
<!--codeinclude-->
|
| 406 |
-
[LLM Factory Usage](../src/utils/llm_factory.py) start_line:129 end_line:144
|
| 407 |
-
<!--/codeinclude-->
|
| 408 |
-
|
| 409 |
-
### Embedding Service
|
| 410 |
-
|
| 411 |
-
The embedding service uses local embedding model configuration:
|
| 412 |
-
|
| 413 |
-
<!--codeinclude-->
|
| 414 |
-
[Embedding Service Usage](../src/services/embeddings.py) start_line:29 end_line:31
|
| 415 |
-
<!--/codeinclude-->
|
| 416 |
-
|
| 417 |
-
### Orchestrator Factory
|
| 418 |
-
|
| 419 |
-
The orchestrator factory uses settings to determine mode:
|
| 420 |
-
|
| 421 |
-
<!--codeinclude-->
|
| 422 |
-
[Orchestrator Factory Mode Detection](../src/orchestrator_factory.py) start_line:97 end_line:110
|
| 423 |
-
<!--/codeinclude-->
|
| 424 |
-
|
| 425 |
-
## Environment Variables Reference
|
| 426 |
-
|
| 427 |
-
### Required (at least one LLM)
|
| 428 |
-
|
| 429 |
-
- `OPENAI_API_KEY` - OpenAI API key (required for OpenAI provider)
|
| 430 |
-
- `ANTHROPIC_API_KEY` - Anthropic API key (required for Anthropic provider)
|
| 431 |
-
- `HF_TOKEN` or `HUGGINGFACE_API_KEY` - HuggingFace API token (optional, can work without for public models)
|
| 432 |
-
|
| 433 |
-
#### LLM Configuration Variables
|
| 434 |
-
|
| 435 |
-
- `LLM_PROVIDER` - Provider to use: `"openai"`, `"anthropic"`, or `"huggingface"` (default: `"huggingface"`)
|
| 436 |
-
- `OPENAI_MODEL` - OpenAI model name (default: `"gpt-5.1"`)
|
| 437 |
-
- `ANTHROPIC_MODEL` - Anthropic model name (default: `"claude-sonnet-4-5-20250929"`)
|
| 438 |
-
- `HUGGINGFACE_MODEL` - HuggingFace model ID (default: `"meta-llama/Llama-3.1-8B-Instruct"`)
|
| 439 |
-
|
| 440 |
-
#### Embedding Configuration Variables
|
| 441 |
-
|
| 442 |
-
- `EMBEDDING_PROVIDER` - Provider: `"openai"`, `"local"`, or `"huggingface"` (default: `"local"`)
|
| 443 |
-
- `OPENAI_EMBEDDING_MODEL` - OpenAI embedding model (default: `"text-embedding-3-small"`)
|
| 444 |
-
- `LOCAL_EMBEDDING_MODEL` - Local sentence-transformers model (default: `"all-MiniLM-L6-v2"`)
|
| 445 |
-
- `HUGGINGFACE_EMBEDDING_MODEL` - HuggingFace embedding model (default: `"sentence-transformers/all-MiniLM-L6-v2"`)
|
| 446 |
-
|
| 447 |
-
#### Web Search Configuration Variables
|
| 448 |
-
|
| 449 |
-
- `WEB_SEARCH_PROVIDER` - Provider: `"serper"`, `"searchxng"`, `"brave"`, `"tavily"`, or `"duckduckgo"` (default: `"duckduckgo"`)
|
| 450 |
-
- `SERPER_API_KEY` - Serper API key (required for Serper provider)
|
| 451 |
-
- `SEARCHXNG_HOST` - SearchXNG host URL (required for SearchXNG provider)
|
| 452 |
-
- `BRAVE_API_KEY` - Brave Search API key (required for Brave provider)
|
| 453 |
-
- `TAVILY_API_KEY` - Tavily API key (required for Tavily provider)
|
| 454 |
-
|
| 455 |
-
#### PubMed Configuration Variables
|
| 456 |
-
|
| 457 |
-
- `NCBI_API_KEY` - NCBI API key (optional, increases rate limit from 3 to 10 req/sec)
|
| 458 |
-
|
| 459 |
-
#### Agent Configuration Variables
|
| 460 |
-
|
| 461 |
-
- `MAX_ITERATIONS` - Maximum iterations per research loop (1-50, default: `10`)
|
| 462 |
-
- `SEARCH_TIMEOUT` - Search timeout in seconds (default: `30`)
|
| 463 |
-
- `USE_GRAPH_EXECUTION` - Use graph-based execution (default: `false`)
|
| 464 |
-
|
| 465 |
-
#### Budget Configuration Variables
|
| 466 |
-
|
| 467 |
-
- `DEFAULT_TOKEN_LIMIT` - Default token budget per research loop (1000-1000000, default: `100000`)
|
| 468 |
-
- `DEFAULT_TIME_LIMIT_MINUTES` - Default time limit in minutes (1-120, default: `10`)
|
| 469 |
-
- `DEFAULT_ITERATIONS_LIMIT` - Default iterations limit (1-50, default: `10`)
|
| 470 |
-
|
| 471 |
-
#### RAG Configuration Variables
|
| 472 |
-
|
| 473 |
-
- `RAG_COLLECTION_NAME` - ChromaDB collection name (default: `"deepcritical_evidence"`)
|
| 474 |
-
- `RAG_SIMILARITY_TOP_K` - Number of top results to retrieve (1-50, default: `5`)
|
| 475 |
-
- `RAG_AUTO_INGEST` - Automatically ingest evidence into RAG (default: `true`)
|
| 476 |
-
|
| 477 |
-
#### ChromaDB Configuration Variables
|
| 478 |
-
|
| 479 |
-
- `CHROMA_DB_PATH` - ChromaDB storage path (default: `"./chroma_db"`)
|
| 480 |
-
- `CHROMA_DB_PERSIST` - Whether to persist ChromaDB to disk (default: `true`)
|
| 481 |
-
- `CHROMA_DB_HOST` - ChromaDB server host (optional, for remote ChromaDB)
|
| 482 |
-
- `CHROMA_DB_PORT` - ChromaDB server port (optional, for remote ChromaDB)
|
| 483 |
-
|
| 484 |
-
#### External Services Variables
|
| 485 |
-
|
| 486 |
-
- `MODAL_TOKEN_ID` - Modal token ID (optional, for Modal sandbox execution)
|
| 487 |
-
- `MODAL_TOKEN_SECRET` - Modal token secret (optional, for Modal sandbox execution)
|
| 488 |
-
|
| 489 |
-
#### Logging Configuration Variables
|
| 490 |
-
|
| 491 |
-
- `LOG_LEVEL` - Log level: `"DEBUG"`, `"INFO"`, `"WARNING"`, or `"ERROR"` (default: `"INFO"`)
|
| 492 |
-
|
| 493 |
-
## Validation
|
| 494 |
-
|
| 495 |
-
Settings are validated on load using Pydantic validation:
|
| 496 |
-
|
| 497 |
-
- **Type Checking**: All fields are strongly typed
|
| 498 |
-
- **Range Validation**: Numeric fields have min/max constraints (e.g., `ge=1, le=50` for `max_iterations`)
|
| 499 |
-
- **Literal Validation**: Enum fields only accept specific values (e.g., `Literal["openai", "anthropic", "huggingface"]`)
|
| 500 |
-
- **Required Fields**: API keys are checked when accessed via `get_api_key()` or `get_openai_api_key()`
|
| 501 |
-
|
| 502 |
-
### Validation Examples
|
| 503 |
-
|
| 504 |
-
The `max_iterations` field has range validation:
|
| 505 |
-
|
| 506 |
-
<!--codeinclude-->
|
| 507 |
-
[Max Iterations Validation](../src/utils/config.py) start_line:81 end_line:81
|
| 508 |
-
<!--/codeinclude-->
|
| 509 |
-
|
| 510 |
-
The `llm_provider` field has literal validation:
|
| 511 |
-
|
| 512 |
-
<!--codeinclude-->
|
| 513 |
-
[LLM Provider Literal Validation](../src/utils/config.py) start_line:26 end_line:28
|
| 514 |
-
<!--/codeinclude-->
|
| 515 |
-
|
| 516 |
-
## Error Handling
|
| 517 |
-
|
| 518 |
-
Configuration errors raise `ConfigurationError` from `src/utils/exceptions.py`:
|
| 519 |
-
|
| 520 |
-
<!--codeinclude-->
|
| 521 |
-
[ConfigurationError Class](../src/utils/exceptions.py) start_line:22 end_line:25
|
| 522 |
-
<!--/codeinclude-->
|
| 523 |
-
|
| 524 |
-
### Error Handling Example
|
| 525 |
-
|
| 526 |
-
```python
|
| 527 |
-
from src.utils.config import settings
|
| 528 |
-
from src.utils.exceptions import ConfigurationError
|
| 529 |
-
|
| 530 |
-
try:
|
| 531 |
-
api_key = settings.get_api_key()
|
| 532 |
-
except ConfigurationError as e:
|
| 533 |
-
print(f"Configuration error: {e}")
|
| 534 |
-
```
|
| 535 |
-
|
| 536 |
-
### Common Configuration Errors
|
| 537 |
-
|
| 538 |
-
1. **Missing API Key**: When `get_api_key()` is called but the required API key is not set
|
| 539 |
-
2. **Invalid Provider**: When `llm_provider` is set to an unsupported value
|
| 540 |
-
3. **Out of Range**: When numeric values exceed their min/max constraints
|
| 541 |
-
4. **Invalid Literal**: When enum fields receive unsupported values
|
| 542 |
-
|
| 543 |
-
## Configuration Best Practices
|
| 544 |
-
|
| 545 |
-
1. **Use `.env` File**: Store sensitive keys in `.env` file (add to `.gitignore`)
|
| 546 |
-
2. **Check Availability**: Use properties like `has_openai_key` before accessing API keys
|
| 547 |
-
3. **Handle Errors**: Always catch `ConfigurationError` when calling `get_api_key()`
|
| 548 |
-
4. **Validate Early**: Configuration is validated on import, so errors surface immediately
|
| 549 |
-
5. **Use Defaults**: Leverage sensible defaults for optional configuration
|
| 550 |
-
|
| 551 |
-
## Future Enhancements
|
| 552 |
-
|
| 553 |
-
The following configurations are planned for future phases:
|
| 554 |
-
|
| 555 |
-
1. **Additional LLM Providers**: DeepSeek, OpenRouter, Gemini, Perplexity, Azure OpenAI, Local models
|
| 556 |
-
2. **Model Selection**: Reasoning/main/fast model configuration
|
| 557 |
-
3. **Service Integration**: Additional service integrations and configurations
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/contributing/code-quality.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
# Code Quality & Documentation
|
| 2 |
|
| 3 |
-
This document outlines code quality standards and documentation requirements.
|
| 4 |
|
| 5 |
## Linting
|
| 6 |
|
|
@@ -12,6 +12,9 @@ This document outlines code quality standards and documentation requirements.
|
|
| 12 |
- `PLR2004`: Magic values (statistical constants)
|
| 13 |
- `PLW0603`: Global statement (singleton pattern)
|
| 14 |
- `PLC0415`: Lazy imports for optional dependencies
|
|
|
|
|
|
|
|
|
|
| 15 |
|
| 16 |
## Type Checking
|
| 17 |
|
|
@@ -22,12 +25,75 @@ This document outlines code quality standards and documentation requirements.
|
|
| 22 |
|
| 23 |
## Pre-commit
|
| 24 |
|
| 25 |
-
-
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
## Documentation
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
### Docstrings
|
| 32 |
|
| 33 |
- Google-style docstrings for all public functions
|
|
|
|
| 1 |
# Code Quality & Documentation
|
| 2 |
|
| 3 |
+
This document outlines code quality standards and documentation requirements for The DETERMINATOR.
|
| 4 |
|
| 5 |
## Linting
|
| 6 |
|
|
|
|
| 12 |
- `PLR2004`: Magic values (statistical constants)
|
| 13 |
- `PLW0603`: Global statement (singleton pattern)
|
| 14 |
- `PLC0415`: Lazy imports for optional dependencies
|
| 15 |
+
- `E402`: Module level import not at top (needed for pytest.importorskip)
|
| 16 |
+
- `E501`: Line too long (ignore line length violations)
|
| 17 |
+
- `RUF100`: Unused noqa (version differences between local/CI)
|
| 18 |
|
| 19 |
## Type Checking
|
| 20 |
|
|
|
|
| 25 |
|
| 26 |
## Pre-commit
|
| 27 |
|
| 28 |
+
Pre-commit hooks run automatically on commit to ensure code quality. Configuration is in `.pre-commit-config.yaml`.
|
| 29 |
+
|
| 30 |
+
### Installation
|
| 31 |
+
|
| 32 |
+
```bash
|
| 33 |
+
# Install dependencies (includes pre-commit package)
|
| 34 |
+
uv sync --all-extras
|
| 35 |
+
|
| 36 |
+
# Set up git hooks (must be run separately)
|
| 37 |
+
uv run pre-commit install
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
**Note**: `uv sync --all-extras` installs the pre-commit package, but you must run `uv run pre-commit install` separately to set up the git hooks.
|
| 41 |
+
|
| 42 |
+
### Pre-commit Hooks
|
| 43 |
+
|
| 44 |
+
The following hooks run automatically on commit:
|
| 45 |
+
|
| 46 |
+
1. **ruff**: Lints code and fixes issues automatically
|
| 47 |
+
- Runs on: `src/` (excludes `tests/`, `reference_repos/`)
|
| 48 |
+
- Auto-fixes: Yes
|
| 49 |
+
|
| 50 |
+
2. **ruff-format**: Formats code with ruff
|
| 51 |
+
- Runs on: `src/` (excludes `tests/`, `reference_repos/`)
|
| 52 |
+
- Auto-fixes: Yes
|
| 53 |
+
|
| 54 |
+
3. **mypy**: Type checking
|
| 55 |
+
- Runs on: `src/` (excludes `folder/`)
|
| 56 |
+
- Additional dependencies: pydantic, pydantic-settings, tenacity, pydantic-ai
|
| 57 |
+
|
| 58 |
+
4. **pytest-unit**: Runs unit tests (excludes OpenAI and embedding_provider tests)
|
| 59 |
+
- Runs: `tests/unit/` with `-m "not openai and not embedding_provider"`
|
| 60 |
+
- Always runs: Yes (not just on changed files)
|
| 61 |
+
|
| 62 |
+
5. **pytest-local-embeddings**: Runs local embedding tests
|
| 63 |
+
- Runs: `tests/` with `-m "local_embeddings"`
|
| 64 |
+
- Always runs: Yes
|
| 65 |
+
|
| 66 |
+
### Manual Pre-commit Run
|
| 67 |
+
|
| 68 |
+
To run pre-commit hooks manually (without committing):
|
| 69 |
+
|
| 70 |
+
```bash
|
| 71 |
+
uv run pre-commit run --all-files
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
### Troubleshooting
|
| 75 |
+
|
| 76 |
+
- **Hooks failing**: Fix the issues shown in the output, then commit again
|
| 77 |
+
- **Skipping hooks**: Use `git commit --no-verify` (not recommended)
|
| 78 |
+
- **Hook not running**: Ensure hooks are installed with `uv run pre-commit install`
|
| 79 |
+
- **Type errors**: Check that all dependencies are installed with `uv sync --all-extras`
|
| 80 |
|
| 81 |
## Documentation
|
| 82 |
|
| 83 |
+
### Building Documentation
|
| 84 |
+
|
| 85 |
+
Documentation is built using MkDocs. Source files are in `docs/`, and the configuration is in `mkdocs.yml`.
|
| 86 |
+
|
| 87 |
+
```bash
|
| 88 |
+
# Build documentation
|
| 89 |
+
uv run mkdocs build
|
| 90 |
+
|
| 91 |
+
# Serve documentation locally (http://127.0.0.1:8000)
|
| 92 |
+
uv run mkdocs serve
|
| 93 |
+
```
|
| 94 |
+
|
| 95 |
+
The documentation site is published at: <https://deepcritical.github.io/GradioDemo/>
|
| 96 |
+
|
| 97 |
### Docstrings
|
| 98 |
|
| 99 |
- Google-style docstrings for all public functions
|
docs/contributing/code-style.md
CHANGED
|
@@ -1,6 +1,44 @@
|
|
| 1 |
# Code Style & Conventions
|
| 2 |
|
| 3 |
-
This document outlines the code style and conventions for
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
## Type Safety
|
| 6 |
|
|
|
|
| 1 |
# Code Style & Conventions
|
| 2 |
|
| 3 |
+
This document outlines the code style and conventions for The DETERMINATOR.
|
| 4 |
+
|
| 5 |
+
## Package Manager
|
| 6 |
+
|
| 7 |
+
This project uses [`uv`](https://github.com/astral-sh/uv) as the package manager. All commands should be prefixed with `uv run` to ensure they run in the correct environment.
|
| 8 |
+
|
| 9 |
+
### Installation
|
| 10 |
+
|
| 11 |
+
```bash
|
| 12 |
+
# Install uv if you haven't already (recommended: standalone installer)
|
| 13 |
+
# Unix/macOS/Linux:
|
| 14 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 15 |
+
|
| 16 |
+
# Windows (PowerShell):
|
| 17 |
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
| 18 |
+
|
| 19 |
+
# Alternative: pipx install uv
|
| 20 |
+
# Or: pip install uv
|
| 21 |
+
|
| 22 |
+
# Sync all dependencies including dev extras
|
| 23 |
+
uv sync --all-extras
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
### Running Commands
|
| 27 |
+
|
| 28 |
+
All development commands should use `uv run` prefix:
|
| 29 |
+
|
| 30 |
+
```bash
|
| 31 |
+
# Instead of: pytest tests/
|
| 32 |
+
uv run pytest tests/
|
| 33 |
+
|
| 34 |
+
# Instead of: ruff check src
|
| 35 |
+
uv run ruff check src
|
| 36 |
+
|
| 37 |
+
# Instead of: mypy src
|
| 38 |
+
uv run mypy src
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
This ensures commands run in the correct virtual environment managed by `uv`.
|
| 42 |
|
| 43 |
## Type Safety
|
| 44 |
|
docs/contributing/error-handling.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
# Error Handling & Logging
|
| 2 |
|
| 3 |
-
This document outlines error handling and logging conventions for
|
| 4 |
|
| 5 |
## Exception Hierarchy
|
| 6 |
|
|
|
|
| 1 |
# Error Handling & Logging
|
| 2 |
|
| 3 |
+
This document outlines error handling and logging conventions for The DETERMINATOR.
|
| 4 |
|
| 5 |
## Exception Hierarchy
|
| 6 |
|
docs/contributing/implementation-patterns.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
# Implementation Patterns
|
| 2 |
|
| 3 |
-
This document outlines common implementation patterns used in
|
| 4 |
|
| 5 |
## Search Tools
|
| 6 |
|
|
|
|
| 1 |
# Implementation Patterns
|
| 2 |
|
| 3 |
+
This document outlines common implementation patterns used in The DETERMINATOR.
|
| 4 |
|
| 5 |
## Search Tools
|
| 6 |
|
docs/contributing/index.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
| 1 |
-
# Contributing to
|
| 2 |
|
| 3 |
-
Thank you for your interest in contributing to
|
|
|
|
|
|
|
| 4 |
|
| 5 |
## Git Workflow
|
| 6 |
|
|
@@ -10,44 +12,138 @@ Thank you for your interest in contributing to DeepCritical! This guide will hel
|
|
| 10 |
- **NEVER** push directly to `main` or `dev` on HuggingFace
|
| 11 |
- GitHub is source of truth; HuggingFace is for deployment
|
| 12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
## Development Commands
|
| 14 |
|
| 15 |
```bash
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
```
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
## Getting Started
|
| 26 |
|
| 27 |
-
1. **Fork the repository** on GitHub
|
|
|
|
| 28 |
2. **Clone your fork**:
|
|
|
|
| 29 |
```bash
|
| 30 |
git clone https://github.com/yourusername/GradioDemo.git
|
| 31 |
cd GradioDemo
|
| 32 |
```
|
|
|
|
| 33 |
3. **Install dependencies**:
|
|
|
|
| 34 |
```bash
|
| 35 |
-
|
|
|
|
| 36 |
```
|
|
|
|
| 37 |
4. **Create a feature branch**:
|
|
|
|
| 38 |
```bash
|
| 39 |
git checkout -b yourname-feature-name
|
| 40 |
```
|
|
|
|
| 41 |
5. **Make your changes** following the guidelines below
|
|
|
|
| 42 |
6. **Run checks**:
|
|
|
|
| 43 |
```bash
|
| 44 |
-
|
|
|
|
|
|
|
| 45 |
```
|
|
|
|
| 46 |
7. **Commit and push**:
|
|
|
|
| 47 |
```bash
|
| 48 |
git commit -m "Description of changes"
|
| 49 |
git push origin yourname-feature-name
|
| 50 |
```
|
|
|
|
| 51 |
8. **Create a pull request** on GitHub
|
| 52 |
|
| 53 |
## Development Guidelines
|
|
@@ -132,7 +228,7 @@ make test-cov # Test with coverage
|
|
| 132 |
|
| 133 |
## Pull Request Process
|
| 134 |
|
| 135 |
-
1. Ensure all checks pass: `
|
| 136 |
2. Update documentation if needed
|
| 137 |
3. Add tests for new features
|
| 138 |
4. Update CHANGELOG if applicable
|
|
@@ -140,10 +236,19 @@ make test-cov # Test with coverage
|
|
| 140 |
6. Address review feedback
|
| 141 |
7. Wait for approval before merging
|
| 142 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
## Questions?
|
| 144 |
|
| 145 |
-
- Open an issue on GitHub
|
| 146 |
-
- Check existing documentation
|
| 147 |
- Review code examples in the codebase
|
| 148 |
|
| 149 |
-
Thank you for contributing to
|
|
|
|
| 1 |
+
# Contributing to The DETERMINATOR
|
| 2 |
|
| 3 |
+
Thank you for your interest in contributing to The DETERMINATOR! This guide will help you get started.
|
| 4 |
+
|
| 5 |
+
> **Note on Project Names**: "The DETERMINATOR" is the product name, "DeepCritical" is the organization/project name, and "determinator" is the Python package name.
|
| 6 |
|
| 7 |
## Git Workflow
|
| 8 |
|
|
|
|
| 12 |
- **NEVER** push directly to `main` or `dev` on HuggingFace
|
| 13 |
- GitHub is source of truth; HuggingFace is for deployment
|
| 14 |
|
| 15 |
+
## Repository Information
|
| 16 |
+
|
| 17 |
+
- **GitHub Repository**: [`DeepCritical/GradioDemo`](https://github.com/DeepCritical/GradioDemo) (source of truth, PRs, code review)
|
| 18 |
+
- **HuggingFace Space**: [`DataQuests/DeepCritical`](https://huggingface.co/spaces/DataQuests/DeepCritical) (deployment/demo)
|
| 19 |
+
- **Package Name**: `determinator` (Python package name in `pyproject.toml`)
|
| 20 |
+
|
| 21 |
+
### Dual Repository Setup
|
| 22 |
+
|
| 23 |
+
This project uses a dual repository setup:
|
| 24 |
+
|
| 25 |
+
- **GitHub (`DeepCritical/GradioDemo`)**: Source of truth for code, PRs, and code review
|
| 26 |
+
- **HuggingFace (`DataQuests/DeepCritical`)**: Deployment target for the Gradio demo
|
| 27 |
+
|
| 28 |
+
#### Remote Configuration
|
| 29 |
+
|
| 30 |
+
When cloning, set up remotes as follows:
|
| 31 |
+
|
| 32 |
+
```bash
|
| 33 |
+
# Clone from GitHub
|
| 34 |
+
git clone https://github.com/DeepCritical/GradioDemo.git
|
| 35 |
+
cd GradioDemo
|
| 36 |
+
|
| 37 |
+
# Add HuggingFace remote (optional, for deployment)
|
| 38 |
+
git remote add huggingface-upstream https://huggingface.co/spaces/DataQuests/DeepCritical
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
**Important**: Never push directly to `main` or `dev` on HuggingFace. Always work through GitHub PRs. GitHub is the source of truth; HuggingFace is for deployment/demo only.
|
| 42 |
+
|
| 43 |
+
## Package Manager
|
| 44 |
+
|
| 45 |
+
This project uses [`uv`](https://github.com/astral-sh/uv) as the package manager. All commands should be prefixed with `uv run` to ensure they run in the correct environment.
|
| 46 |
+
|
| 47 |
+
### Installation
|
| 48 |
+
|
| 49 |
+
```bash
|
| 50 |
+
# Install uv if you haven't already (recommended: standalone installer)
|
| 51 |
+
# Unix/macOS/Linux:
|
| 52 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 53 |
+
|
| 54 |
+
# Windows (PowerShell):
|
| 55 |
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
| 56 |
+
|
| 57 |
+
# Alternative: pipx install uv
|
| 58 |
+
# Or: pip install uv
|
| 59 |
+
|
| 60 |
+
# Sync all dependencies including dev extras
|
| 61 |
+
uv sync --all-extras
|
| 62 |
+
|
| 63 |
+
# Install pre-commit hooks
|
| 64 |
+
uv run pre-commit install
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
## Development Commands
|
| 68 |
|
| 69 |
```bash
|
| 70 |
+
# Installation
|
| 71 |
+
uv sync --all-extras # Install all dependencies including dev
|
| 72 |
+
uv run pre-commit install # Install pre-commit hooks
|
| 73 |
+
|
| 74 |
+
# Code Quality Checks (run all before committing)
|
| 75 |
+
uv run ruff check src tests # Lint with ruff
|
| 76 |
+
uv run ruff format src tests # Format with ruff
|
| 77 |
+
uv run mypy src # Type checking
|
| 78 |
+
uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire # Tests with coverage
|
| 79 |
+
|
| 80 |
+
# Testing Commands
|
| 81 |
+
uv run pytest tests/unit/ -v -m "not openai" -p no:logfire # Run unit tests (excludes OpenAI tests)
|
| 82 |
+
uv run pytest tests/ -v -m "huggingface" -p no:logfire # Run HuggingFace tests
|
| 83 |
+
uv run pytest tests/ -v -p no:logfire # Run all tests
|
| 84 |
+
uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire # Tests with terminal coverage
|
| 85 |
+
uv run pytest --cov=src --cov-report=html -p no:logfire # Generate HTML coverage report (opens htmlcov/index.html)
|
| 86 |
+
|
| 87 |
+
# Documentation Commands
|
| 88 |
+
uv run mkdocs build # Build documentation
|
| 89 |
+
uv run mkdocs serve # Serve documentation locally (http://127.0.0.1:8000)
|
| 90 |
```
|
| 91 |
|
| 92 |
+
### Test Markers
|
| 93 |
+
|
| 94 |
+
The project uses pytest markers to categorize tests. See [Testing Guidelines](testing.md) for details:
|
| 95 |
+
|
| 96 |
+
- `unit`: Unit tests (mocked, fast)
|
| 97 |
+
- `integration`: Integration tests (real APIs)
|
| 98 |
+
- `slow`: Slow tests
|
| 99 |
+
- `openai`: Tests requiring OpenAI API key
|
| 100 |
+
- `huggingface`: Tests requiring HuggingFace API key
|
| 101 |
+
- `embedding_provider`: Tests requiring API-based embedding providers
|
| 102 |
+
- `local_embeddings`: Tests using local embeddings
|
| 103 |
+
|
| 104 |
+
**Note**: The `-p no:logfire` flag disables the logfire plugin to avoid conflicts during testing.
|
| 105 |
+
|
| 106 |
## Getting Started
|
| 107 |
|
| 108 |
+
1. **Fork the repository** on GitHub: [`DeepCritical/GradioDemo`](https://github.com/DeepCritical/GradioDemo)
|
| 109 |
+
|
| 110 |
2. **Clone your fork**:
|
| 111 |
+
|
| 112 |
```bash
|
| 113 |
git clone https://github.com/yourusername/GradioDemo.git
|
| 114 |
cd GradioDemo
|
| 115 |
```
|
| 116 |
+
|
| 117 |
3. **Install dependencies**:
|
| 118 |
+
|
| 119 |
```bash
|
| 120 |
+
uv sync --all-extras
|
| 121 |
+
uv run pre-commit install
|
| 122 |
```
|
| 123 |
+
|
| 124 |
4. **Create a feature branch**:
|
| 125 |
+
|
| 126 |
```bash
|
| 127 |
git checkout -b yourname-feature-name
|
| 128 |
```
|
| 129 |
+
|
| 130 |
5. **Make your changes** following the guidelines below
|
| 131 |
+
|
| 132 |
6. **Run checks**:
|
| 133 |
+
|
| 134 |
```bash
|
| 135 |
+
uv run ruff check src tests
|
| 136 |
+
uv run mypy src
|
| 137 |
+
uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire
|
| 138 |
```
|
| 139 |
+
|
| 140 |
7. **Commit and push**:
|
| 141 |
+
|
| 142 |
```bash
|
| 143 |
git commit -m "Description of changes"
|
| 144 |
git push origin yourname-feature-name
|
| 145 |
```
|
| 146 |
+
|
| 147 |
8. **Create a pull request** on GitHub
|
| 148 |
|
| 149 |
## Development Guidelines
|
|
|
|
| 228 |
|
| 229 |
## Pull Request Process
|
| 230 |
|
| 231 |
+
1. Ensure all checks pass: `uv run ruff check src tests && uv run mypy src && uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire`
|
| 232 |
2. Update documentation if needed
|
| 233 |
3. Add tests for new features
|
| 234 |
4. Update CHANGELOG if applicable
|
|
|
|
| 236 |
6. Address review feedback
|
| 237 |
7. Wait for approval before merging
|
| 238 |
|
| 239 |
+
## Project Structure
|
| 240 |
+
|
| 241 |
+
- `src/`: Main source code
|
| 242 |
+
- `tests/`: Test files (`unit/` and `integration/`)
|
| 243 |
+
- `docs/`: Documentation source files (MkDocs)
|
| 244 |
+
- `examples/`: Example usage scripts
|
| 245 |
+
- `pyproject.toml`: Project configuration and dependencies
|
| 246 |
+
- `.pre-commit-config.yaml`: Pre-commit hook configuration
|
| 247 |
+
|
| 248 |
## Questions?
|
| 249 |
|
| 250 |
+
- Open an issue on [GitHub](https://github.com/DeepCritical/GradioDemo)
|
| 251 |
+
- Check existing [documentation](https://deepcritical.github.io/GradioDemo/)
|
| 252 |
- Review code examples in the codebase
|
| 253 |
|
| 254 |
+
Thank you for contributing to The DETERMINATOR!
|
docs/contributing/testing.md
CHANGED
|
@@ -1,12 +1,45 @@
|
|
| 1 |
# Testing Requirements
|
| 2 |
|
| 3 |
-
This document outlines testing requirements and guidelines for
|
| 4 |
|
| 5 |
## Test Structure
|
| 6 |
|
| 7 |
- Unit tests in `tests/unit/` (mocked, fast)
|
| 8 |
- Integration tests in `tests/integration/` (real APIs, marked `@pytest.mark.integration`)
|
| 9 |
-
- Use markers: `unit`, `integration`, `slow`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
## Mocking
|
| 12 |
|
|
@@ -20,7 +53,20 @@ This document outlines testing requirements and guidelines for DeepCritical.
|
|
| 20 |
1. Write failing test in `tests/unit/`
|
| 21 |
2. Implement in `src/`
|
| 22 |
3. Ensure test passes
|
| 23 |
-
4. Run `
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
## Test Examples
|
| 26 |
|
|
@@ -41,9 +87,27 @@ async def test_real_pubmed_search():
|
|
| 41 |
|
| 42 |
## Test Coverage
|
| 43 |
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
- Aim for >80% coverage on critical paths
|
| 46 |
- Exclude: `__init__.py`, `TYPE_CHECKING` blocks
|
|
|
|
| 47 |
|
| 48 |
## See Also
|
| 49 |
|
|
|
|
| 1 |
# Testing Requirements
|
| 2 |
|
| 3 |
+
This document outlines testing requirements and guidelines for The DETERMINATOR.
|
| 4 |
|
| 5 |
## Test Structure
|
| 6 |
|
| 7 |
- Unit tests in `tests/unit/` (mocked, fast)
|
| 8 |
- Integration tests in `tests/integration/` (real APIs, marked `@pytest.mark.integration`)
|
| 9 |
+
- Use markers: `unit`, `integration`, `slow`, `openai`, `huggingface`, `embedding_provider`, `local_embeddings`
|
| 10 |
+
|
| 11 |
+
## Test Markers
|
| 12 |
+
|
| 13 |
+
The project uses pytest markers to categorize tests. These markers are defined in `pyproject.toml`:
|
| 14 |
+
|
| 15 |
+
- `@pytest.mark.unit`: Unit tests (mocked, fast) - Run with `-m "unit"`
|
| 16 |
+
- `@pytest.mark.integration`: Integration tests (real APIs) - Run with `-m "integration"`
|
| 17 |
+
- `@pytest.mark.slow`: Slow tests - Run with `-m "slow"`
|
| 18 |
+
- `@pytest.mark.openai`: Tests requiring OpenAI API key - Run with `-m "openai"` or exclude with `-m "not openai"`
|
| 19 |
+
- `@pytest.mark.huggingface`: Tests requiring HuggingFace API key or using HuggingFace models - Run with `-m "huggingface"`
|
| 20 |
+
- `@pytest.mark.embedding_provider`: Tests requiring API-based embedding providers (OpenAI, etc.) - Run with `-m "embedding_provider"`
|
| 21 |
+
- `@pytest.mark.local_embeddings`: Tests using local embeddings (sentence-transformers, ChromaDB) - Run with `-m "local_embeddings"`
|
| 22 |
+
|
| 23 |
+
### Running Tests by Marker
|
| 24 |
+
|
| 25 |
+
```bash
|
| 26 |
+
# Run only unit tests (excludes OpenAI tests by default)
|
| 27 |
+
uv run pytest tests/unit/ -v -m "not openai" -p no:logfire
|
| 28 |
+
|
| 29 |
+
# Run HuggingFace tests
|
| 30 |
+
uv run pytest tests/ -v -m "huggingface" -p no:logfire
|
| 31 |
+
|
| 32 |
+
# Run all tests
|
| 33 |
+
uv run pytest tests/ -v -p no:logfire
|
| 34 |
+
|
| 35 |
+
# Run only local embedding tests
|
| 36 |
+
uv run pytest tests/ -v -m "local_embeddings" -p no:logfire
|
| 37 |
+
|
| 38 |
+
# Exclude slow tests
|
| 39 |
+
uv run pytest tests/ -v -m "not slow" -p no:logfire
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
**Note**: The `-p no:logfire` flag disables the logfire plugin to avoid conflicts during testing.
|
| 43 |
|
| 44 |
## Mocking
|
| 45 |
|
|
|
|
| 53 |
1. Write failing test in `tests/unit/`
|
| 54 |
2. Implement in `src/`
|
| 55 |
3. Ensure test passes
|
| 56 |
+
4. Run checks: `uv run ruff check src tests && uv run mypy src && uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire`
|
| 57 |
+
|
| 58 |
+
### Test Command Examples
|
| 59 |
+
|
| 60 |
+
```bash
|
| 61 |
+
# Run unit tests (default, excludes OpenAI tests)
|
| 62 |
+
uv run pytest tests/unit/ -v -m "not openai" -p no:logfire
|
| 63 |
+
|
| 64 |
+
# Run HuggingFace tests
|
| 65 |
+
uv run pytest tests/ -v -m "huggingface" -p no:logfire
|
| 66 |
+
|
| 67 |
+
# Run all tests
|
| 68 |
+
uv run pytest tests/ -v -p no:logfire
|
| 69 |
+
```
|
| 70 |
|
| 71 |
## Test Examples
|
| 72 |
|
|
|
|
| 87 |
|
| 88 |
## Test Coverage
|
| 89 |
|
| 90 |
+
### Terminal Coverage Report
|
| 91 |
+
|
| 92 |
+
```bash
|
| 93 |
+
uv run pytest --cov=src --cov-report=term-missing tests/unit/ -v -m "not openai" -p no:logfire
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
This shows coverage with missing lines highlighted in the terminal output.
|
| 97 |
+
|
| 98 |
+
### HTML Coverage Report
|
| 99 |
+
|
| 100 |
+
```bash
|
| 101 |
+
uv run pytest --cov=src --cov-report=html -p no:logfire
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
This generates an HTML coverage report in `htmlcov/index.html`. Open this file in your browser to see detailed coverage information.
|
| 105 |
+
|
| 106 |
+
### Coverage Goals
|
| 107 |
+
|
| 108 |
- Aim for >80% coverage on critical paths
|
| 109 |
- Exclude: `__init__.py`, `TYPE_CHECKING` blocks
|
| 110 |
+
- Coverage configuration is in `pyproject.toml` under `[tool.coverage.*]`
|
| 111 |
|
| 112 |
## See Also
|
| 113 |
|
docs/getting-started/examples.md
CHANGED
|
@@ -25,6 +25,7 @@ What clinical trials are investigating metformin for cancer prevention?
|
|
| 25 |
```
|
| 26 |
|
| 27 |
**What The DETERMINATOR Does**:
|
|
|
|
| 28 |
1. Searches ClinicalTrials.gov for relevant trials
|
| 29 |
2. Searches PubMed for supporting literature
|
| 30 |
3. Provides trial details and status
|
|
@@ -35,6 +36,7 @@ What clinical trials are investigating metformin for cancer prevention?
|
|
| 35 |
### Example 3: Comprehensive Review
|
| 36 |
|
| 37 |
**Query**:
|
|
|
|
| 38 |
```
|
| 39 |
Review the evidence for using metformin as an anti-aging intervention,
|
| 40 |
including clinical trials, mechanisms of action, and safety profile.
|
|
@@ -194,25 +196,3 @@ USE_GRAPH_EXECUTION=true
|
|
| 194 |
- Explore the [Architecture Documentation](../architecture/graph_orchestration.md)
|
| 195 |
- Check out the [API Reference](../api/agents.md) for programmatic usage
|
| 196 |
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
<<<<<<< Updated upstream
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
=======
|
| 218 |
-
>>>>>>> Stashed changes
|
|
|
|
| 25 |
```
|
| 26 |
|
| 27 |
**What The DETERMINATOR Does**:
|
| 28 |
+
|
| 29 |
1. Searches ClinicalTrials.gov for relevant trials
|
| 30 |
2. Searches PubMed for supporting literature
|
| 31 |
3. Provides trial details and status
|
|
|
|
| 36 |
### Example 3: Comprehensive Review
|
| 37 |
|
| 38 |
**Query**:
|
| 39 |
+
|
| 40 |
```
|
| 41 |
Review the evidence for using metformin as an anti-aging intervention,
|
| 42 |
including clinical trials, mechanisms of action, and safety profile.
|
|
|
|
| 196 |
- Explore the [Architecture Documentation](../architecture/graph_orchestration.md)
|
| 197 |
- Check out the [API Reference](../api/agents.md) for programmatic usage
|
| 198 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/getting-started/installation.md
CHANGED
|
@@ -12,12 +12,29 @@ This guide will help you install and set up DeepCritical on your system.
|
|
| 12 |
|
| 13 |
### 1. Install uv (Recommended)
|
| 14 |
|
| 15 |
-
`uv` is a fast Python package installer and resolver. Install it
|
| 16 |
|
|
|
|
| 17 |
```bash
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
pip install uv
|
| 19 |
```
|
| 20 |
|
|
|
|
|
|
|
| 21 |
### 2. Clone the Repository
|
| 22 |
|
| 23 |
```bash
|
|
@@ -133,40 +150,3 @@ uv run pre-commit install
|
|
| 133 |
- Learn about [MCP Integration](mcp-integration.md)
|
| 134 |
- Explore [Examples](examples.md)
|
| 135 |
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
<<<<<<< HEAD
|
| 150 |
-
<<<<<<< Updated upstream
|
| 151 |
-
=======
|
| 152 |
-
=======
|
| 153 |
-
>>>>>>> 8086ce5fefde1c867880661d57e1299029a91ead
|
| 154 |
-
|
| 155 |
-
<<<<<<< Updated upstream
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
=======
|
| 162 |
-
>>>>>>> Stashed changes
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
<<<<<<< HEAD
|
| 168 |
-
|
| 169 |
-
>>>>>>> Stashed changes
|
| 170 |
-
|
| 171 |
-
=======
|
| 172 |
-
>>>>>>> 8086ce5fefde1c867880661d57e1299029a91ead
|
|
|
|
| 12 |
|
| 13 |
### 1. Install uv (Recommended)
|
| 14 |
|
| 15 |
+
`uv` is a fast Python package installer and resolver. Install it using the standalone installer (recommended):
|
| 16 |
|
| 17 |
+
**Unix/macOS/Linux:**
|
| 18 |
```bash
|
| 19 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
**Windows (PowerShell):**
|
| 23 |
+
```powershell
|
| 24 |
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
**Alternative methods:**
|
| 28 |
+
```bash
|
| 29 |
+
# Using pipx (recommended if you have pipx installed)
|
| 30 |
+
pipx install uv
|
| 31 |
+
|
| 32 |
+
# Or using pip
|
| 33 |
pip install uv
|
| 34 |
```
|
| 35 |
|
| 36 |
+
After installation, restart your terminal or add `~/.cargo/bin` to your PATH.
|
| 37 |
+
|
| 38 |
### 2. Clone the Repository
|
| 39 |
|
| 40 |
```bash
|
|
|
|
| 150 |
- Learn about [MCP Integration](mcp-integration.md)
|
| 151 |
- Explore [Examples](examples.md)
|
| 152 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/getting-started/mcp-integration.md
CHANGED
|
@@ -201,16 +201,3 @@ You can configure multiple DeepCritical instances:
|
|
| 201 |
- Read the [Architecture Documentation](../architecture/graph_orchestration.md)
|
| 202 |
|
| 203 |
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
|
|
|
| 201 |
- Read the [Architecture Documentation](../architecture/graph_orchestration.md)
|
| 202 |
|
| 203 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/getting-started/quick-start.md
CHANGED
|
@@ -41,7 +41,7 @@ Get up and running with The DETERMINATOR in minutes.
|
|
| 41 |
## Start the Application
|
| 42 |
|
| 43 |
```bash
|
| 44 |
-
|
| 45 |
```
|
| 46 |
|
| 47 |
Open your browser to `http://localhost:7860`.
|
|
@@ -140,25 +140,3 @@ What are the active clinical trials investigating Alzheimer's disease treatments
|
|
| 140 |
- Read the [Configuration Guide](../configuration/index.md) for advanced settings
|
| 141 |
- Check out the [Architecture Documentation](../architecture/graph_orchestration.md) to understand how it works
|
| 142 |
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
<<<<<<< Updated upstream
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
=======
|
| 164 |
-
>>>>>>> Stashed changes
|
|
|
|
| 41 |
## Start the Application
|
| 42 |
|
| 43 |
```bash
|
| 44 |
+
gradio src/app.py
|
| 45 |
```
|
| 46 |
|
| 47 |
Open your browser to `http://localhost:7860`.
|
|
|
|
| 140 |
- Read the [Configuration Guide](../configuration/index.md) for advanced settings
|
| 141 |
- Check out the [Architecture Documentation](../architecture/graph_orchestration.md) to understand how it works
|
| 142 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation/IMPLEMENTATION_SUMMARY.md
DELETED
|
@@ -1,188 +0,0 @@
|
|
| 1 |
-
# Multimodal Audio & Image Integration - Implementation Summary
|
| 2 |
-
|
| 3 |
-
## ✅ Completed Implementation
|
| 4 |
-
|
| 5 |
-
### 1. Configuration System (`src/utils/config.py`)
|
| 6 |
-
- ✅ Added audio configuration fields:
|
| 7 |
-
- `tts_model`, `tts_voice`, `tts_speed`, `tts_gpu`, `tts_timeout`
|
| 8 |
-
- `stt_api_url`, `stt_source_lang`, `stt_target_lang`
|
| 9 |
-
- `enable_audio_input`, `enable_audio_output`
|
| 10 |
-
- ✅ Added image OCR configuration:
|
| 11 |
-
- `ocr_api_url`, `enable_image_input`
|
| 12 |
-
- ✅ Added property methods: `audio_available`, `image_ocr_available`
|
| 13 |
-
|
| 14 |
-
### 2. STT Service (`src/services/stt_gradio.py`)
|
| 15 |
-
- ✅ Gradio Client integration for nvidia/canary-1b-v2
|
| 16 |
-
- ✅ Supports file and numpy array audio input
|
| 17 |
-
- ✅ Async transcription with error handling
|
| 18 |
-
- ✅ Singleton factory pattern
|
| 19 |
-
|
| 20 |
-
### 3. TTS Service (`src/services/tts_modal.py`)
|
| 21 |
-
- ✅ **Modal GPU function implementation** following Modal documentation
|
| 22 |
-
- ✅ Kokoro 82M integration via Modal GPU
|
| 23 |
-
- ✅ Module-level function definition with lazy initialization
|
| 24 |
-
- ✅ GPU configuration (T4, A10, A100, L4, L40S)
|
| 25 |
-
- ✅ Async wrapper for TTS synthesis
|
| 26 |
-
- ✅ Error handling and graceful degradation
|
| 27 |
-
|
| 28 |
-
### 4. Image OCR Service (`src/services/image_ocr.py`)
|
| 29 |
-
- ✅ Gradio Client integration for prithivMLmods/Multimodal-OCR3
|
| 30 |
-
- ✅ Supports image files and PIL/numpy arrays
|
| 31 |
-
- ✅ Text extraction from API results
|
| 32 |
-
- ✅ Singleton factory pattern
|
| 33 |
-
|
| 34 |
-
### 5. Unified Services
|
| 35 |
-
- ✅ `src/services/audio_processing.py` - Audio service layer
|
| 36 |
-
- ✅ `src/services/multimodal_processing.py` - Multimodal service layer
|
| 37 |
-
|
| 38 |
-
### 6. ChatInterface Integration (`src/app.py`)
|
| 39 |
-
- ✅ Enabled `multimodal=True` for MultimodalTextbox
|
| 40 |
-
- ✅ Added Audio output component
|
| 41 |
-
- ✅ Integrated STT/TTS/OCR into research flow
|
| 42 |
-
- ✅ Multimodal input processing (text + images + audio)
|
| 43 |
-
- ✅ TTS output generation for final responses
|
| 44 |
-
- ✅ **Configuration UI in Settings Accordion**:
|
| 45 |
-
- Voice dropdown (20+ Kokoro voices)
|
| 46 |
-
- Speed slider (0.5x to 2.0x)
|
| 47 |
-
- GPU dropdown (T4, A10, A100, L4, L40S) - read-only, requires restart
|
| 48 |
-
- Enable audio output checkbox
|
| 49 |
-
- ✅ Configuration values passed from UI to TTS service
|
| 50 |
-
|
| 51 |
-
### 7. MCP Integration (`src/mcp_tools.py`)
|
| 52 |
-
- ✅ Added `extract_text_from_image` MCP tool
|
| 53 |
-
- ✅ Added `transcribe_audio_file` MCP tool
|
| 54 |
-
- ✅ Enabled MCP server in app launch
|
| 55 |
-
|
| 56 |
-
### 8. Dependencies (`pyproject.toml`)
|
| 57 |
-
- ✅ Added audio dependencies (gradio-client, soundfile, Pillow)
|
| 58 |
-
- ✅ Added TTS optional dependencies (torch, transformers)
|
| 59 |
-
- ✅ Installed via `uv add --optional`
|
| 60 |
-
|
| 61 |
-
## 🔧 Modal GPU Implementation Details
|
| 62 |
-
|
| 63 |
-
### Function Definition Pattern
|
| 64 |
-
The Modal GPU function is defined using Modal's recommended pattern:
|
| 65 |
-
|
| 66 |
-
```python
|
| 67 |
-
@app.function(
|
| 68 |
-
image=tts_image, # Image with Kokoro dependencies
|
| 69 |
-
gpu="T4", # GPU type from settings.tts_gpu
|
| 70 |
-
timeout=60, # Timeout from settings.tts_timeout
|
| 71 |
-
)
|
| 72 |
-
def kokoro_tts_function(text: str, voice: str, speed: float) -> tuple[int, np.ndarray]:
|
| 73 |
-
"""Modal GPU function for Kokoro TTS."""
|
| 74 |
-
from kokoro import KModel, KPipeline
|
| 75 |
-
import torch
|
| 76 |
-
|
| 77 |
-
model = KModel().to("cuda").eval()
|
| 78 |
-
pipeline = KPipeline(lang_code=voice[0])
|
| 79 |
-
pack = pipeline.load_voice(voice)
|
| 80 |
-
|
| 81 |
-
for _, ps, _ in pipeline(text, voice, speed):
|
| 82 |
-
ref_s = pack[len(ps) - 1]
|
| 83 |
-
audio = model(ps, ref_s, speed)
|
| 84 |
-
return (24000, audio.numpy())
|
| 85 |
-
```
|
| 86 |
-
|
| 87 |
-
### Key Implementation Points
|
| 88 |
-
1. **Module-Level Definition**: Function defined inside `_setup_modal_function()` but attached to app instance
|
| 89 |
-
2. **Lazy Initialization**: Function set up on first use
|
| 90 |
-
3. **GPU Configuration**: Set at function definition time (requires restart to change)
|
| 91 |
-
4. **Runtime Parameters**: Voice and speed can be changed at runtime via UI
|
| 92 |
-
|
| 93 |
-
## 🔗 Configuration Flow
|
| 94 |
-
|
| 95 |
-
### Settings → Implementation
|
| 96 |
-
1. `settings.tts_voice` → Default voice (used if UI not configured)
|
| 97 |
-
2. `settings.tts_speed` → Default speed (used if UI not configured)
|
| 98 |
-
3. `settings.tts_gpu` → GPU type (set at function definition, requires restart)
|
| 99 |
-
4. `settings.tts_timeout` → Timeout (set at function definition)
|
| 100 |
-
|
| 101 |
-
### UI → Implementation
|
| 102 |
-
1. Voice dropdown → `tts_voice` parameter → `AudioService.generate_audio_output()`
|
| 103 |
-
2. Speed slider → `tts_speed` parameter → `AudioService.generate_audio_output()`
|
| 104 |
-
3. GPU dropdown → Informational only (changes require restart)
|
| 105 |
-
4. Enable checkbox → `settings.enable_audio_output` → Controls TTS generation
|
| 106 |
-
|
| 107 |
-
### Implementation → Modal
|
| 108 |
-
1. `TTSService.synthesize_async()` → Calls Modal GPU function
|
| 109 |
-
2. Modal function executes on GPU → Returns audio tuple
|
| 110 |
-
3. Audio tuple → Gradio Audio component → User hears response
|
| 111 |
-
|
| 112 |
-
## 📋 Configuration Points in UI
|
| 113 |
-
|
| 114 |
-
### Settings Accordion Components
|
| 115 |
-
Located in `src/app.py` lines 667-712:
|
| 116 |
-
|
| 117 |
-
1. **Voice Dropdown** (`tts_voice_dropdown`)
|
| 118 |
-
- 20+ Kokoro voices
|
| 119 |
-
- Default: `settings.tts_voice`
|
| 120 |
-
- Connected to `research_agent()` function
|
| 121 |
-
|
| 122 |
-
2. **Speed Slider** (`tts_speed_slider`)
|
| 123 |
-
- Range: 0.5 to 2.0
|
| 124 |
-
- Step: 0.1
|
| 125 |
-
- Default: `settings.tts_speed`
|
| 126 |
-
- Connected to `research_agent()` function
|
| 127 |
-
|
| 128 |
-
3. **GPU Dropdown** (`tts_gpu_dropdown`)
|
| 129 |
-
- Choices: T4, A10, A100, L4, L40S
|
| 130 |
-
- Default: `settings.tts_gpu or "T4"`
|
| 131 |
-
- Read-only (interactive=False)
|
| 132 |
-
- Note: Changes require app restart
|
| 133 |
-
|
| 134 |
-
4. **Enable Audio Output** (`enable_audio_output_checkbox`)
|
| 135 |
-
- Default: `settings.enable_audio_output`
|
| 136 |
-
- Controls whether TTS is generated
|
| 137 |
-
|
| 138 |
-
## 🎯 Usage Flow
|
| 139 |
-
|
| 140 |
-
1. User opens Settings accordion
|
| 141 |
-
2. Configures TTS voice and speed (optional)
|
| 142 |
-
3. Submits query (text, image, or audio)
|
| 143 |
-
4. Research agent processes query
|
| 144 |
-
5. Final response generated
|
| 145 |
-
6. If audio output enabled:
|
| 146 |
-
- `AudioService.generate_audio_output()` called
|
| 147 |
-
- Uses UI-configured voice/speed or settings defaults
|
| 148 |
-
- Modal GPU function synthesizes audio
|
| 149 |
-
- Audio displayed in Audio component
|
| 150 |
-
|
| 151 |
-
## 📝 Notes
|
| 152 |
-
|
| 153 |
-
- **GPU Changes**: GPU type is set at Modal function definition time. Changes to `settings.tts_gpu` or UI dropdown require app restart.
|
| 154 |
-
- **Voice/Speed Changes**: Can be changed at runtime via UI - no restart required.
|
| 155 |
-
- **Graceful Degradation**: If TTS fails, application continues with text-only response.
|
| 156 |
-
- **Modal Credentials**: Required for TTS. If not configured, TTS service unavailable (graceful fallback).
|
| 157 |
-
|
| 158 |
-
## ✅ Verification Checklist
|
| 159 |
-
|
| 160 |
-
- [x] Modal GPU function correctly defined with `@app.function` decorator
|
| 161 |
-
- [x] GPU parameter set from `settings.tts_gpu`
|
| 162 |
-
- [x] Timeout parameter set from `settings.tts_timeout`
|
| 163 |
-
- [x] Voice parameter passed from UI dropdown
|
| 164 |
-
- [x] Speed parameter passed from UI slider
|
| 165 |
-
- [x] Configuration UI elements in Settings accordion
|
| 166 |
-
- [x] Configuration values connected to implementation
|
| 167 |
-
- [x] Dependencies installed via uv
|
| 168 |
-
- [x] Error handling and graceful degradation
|
| 169 |
-
- [x] MCP tools added for audio/image processing
|
| 170 |
-
|
| 171 |
-
## 🚀 Next Steps
|
| 172 |
-
|
| 173 |
-
1. Test TTS with Modal credentials configured
|
| 174 |
-
2. Verify GPU function execution on Modal
|
| 175 |
-
3. Test voice and speed changes at runtime
|
| 176 |
-
4. Add unit tests for services
|
| 177 |
-
5. Add integration tests for Modal TTS
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation/TOKEN_AUTHENTICATION_REVIEW.md
DELETED
|
@@ -1,201 +0,0 @@
|
|
| 1 |
-
# Token Authentication Review - Gradio & HuggingFace
|
| 2 |
-
|
| 3 |
-
## Summary
|
| 4 |
-
|
| 5 |
-
This document reviews the implementation of token authentication for Gradio Client API calls and HuggingFace API usage to ensure tokens are always passed correctly.
|
| 6 |
-
|
| 7 |
-
## ✅ Implementation Status
|
| 8 |
-
|
| 9 |
-
### 1. Gradio Client Services
|
| 10 |
-
|
| 11 |
-
#### STT Service (`src/services/stt_gradio.py`)
|
| 12 |
-
- ✅ **Token Support**: Service accepts `hf_token` parameter in `__init__` and methods
|
| 13 |
-
- ✅ **Client Initialization**: `Client` is created with `hf_token` parameter when token is available
|
| 14 |
-
- ✅ **Token Priority**: Method-level token > instance-level token
|
| 15 |
-
- ✅ **Token Updates**: Client is recreated if token changes
|
| 16 |
-
|
| 17 |
-
**Implementation Pattern:**
|
| 18 |
-
```python
|
| 19 |
-
async def _get_client(self, hf_token: str | None = None) -> Client:
|
| 20 |
-
token = hf_token or self.hf_token
|
| 21 |
-
if token:
|
| 22 |
-
self.client = Client(self.api_url, hf_token=token)
|
| 23 |
-
else:
|
| 24 |
-
self.client = Client(self.api_url)
|
| 25 |
-
```
|
| 26 |
-
|
| 27 |
-
#### Image OCR Service (`src/services/image_ocr.py`)
|
| 28 |
-
- ✅ **Token Support**: Service accepts `hf_token` parameter in `__init__` and methods
|
| 29 |
-
- ✅ **Client Initialization**: `Client` is created with `hf_token` parameter when token is available
|
| 30 |
-
- ✅ **Token Priority**: Method-level token > instance-level token
|
| 31 |
-
- ✅ **Token Updates**: Client is recreated if token changes
|
| 32 |
-
|
| 33 |
-
**Same pattern as STT Service**
|
| 34 |
-
|
| 35 |
-
### 2. Service Layer Integration
|
| 36 |
-
|
| 37 |
-
#### Audio Service (`src/services/audio_processing.py`)
|
| 38 |
-
- ✅ **Token Passthrough**: `process_audio_input()` accepts `hf_token` and passes to STT service
|
| 39 |
-
- ✅ **Token Flow**: `audio_service.process_audio_input(audio, hf_token=token)`
|
| 40 |
-
|
| 41 |
-
#### Multimodal Service (`src/services/multimodal_processing.py`)
|
| 42 |
-
- ✅ **Token Passthrough**: `process_multimodal_input()` accepts `hf_token` and passes to both audio and OCR services
|
| 43 |
-
- ✅ **Token Flow**: `multimodal_service.process_multimodal_input(..., hf_token=token)`
|
| 44 |
-
|
| 45 |
-
### 3. Application Layer (`src/app.py`)
|
| 46 |
-
|
| 47 |
-
#### Token Extraction
|
| 48 |
-
- ✅ **OAuth Token**: Extracted from `gr.OAuthToken` via `oauth_token.token`
|
| 49 |
-
- ✅ **Fallback**: Uses `HF_TOKEN` or `HUGGINGFACE_API_KEY` from environment
|
| 50 |
-
- ✅ **Token Priority**: `oauth_token > HF_TOKEN > HUGGINGFACE_API_KEY`
|
| 51 |
-
|
| 52 |
-
**Implementation:**
|
| 53 |
-
```python
|
| 54 |
-
token_value: str | None = None
|
| 55 |
-
if oauth_token is not None:
|
| 56 |
-
token_value = oauth_token.token if hasattr(oauth_token, "token") else None
|
| 57 |
-
|
| 58 |
-
# Fallback to env vars
|
| 59 |
-
effective_token = token_value or os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACE_API_KEY")
|
| 60 |
-
```
|
| 61 |
-
|
| 62 |
-
#### Token Usage in Services
|
| 63 |
-
- ✅ **Multimodal Processing**: Token passed to `process_multimodal_input(..., hf_token=token_value)`
|
| 64 |
-
- ✅ **Consistent Usage**: Token is extracted once and passed through all service layers
|
| 65 |
-
|
| 66 |
-
### 4. HuggingFace API Integration
|
| 67 |
-
|
| 68 |
-
#### LLM Factory (`src/utils/llm_factory.py`)
|
| 69 |
-
- ✅ **Token Priority**: `oauth_token > settings.hf_token > settings.huggingface_api_key`
|
| 70 |
-
- ✅ **Provider Usage**: `HuggingFaceProvider(api_key=effective_hf_token)`
|
| 71 |
-
- ✅ **Model Usage**: `HuggingFaceModel(model_name, provider=provider)`
|
| 72 |
-
|
| 73 |
-
#### Judge Handler (`src/agent_factory/judges.py`)
|
| 74 |
-
- ✅ **Token Priority**: `oauth_token > settings.hf_token > settings.huggingface_api_key`
|
| 75 |
-
- ✅ **InferenceClient**: `InferenceClient(api_key=api_key)` when token provided
|
| 76 |
-
- ✅ **Fallback**: Uses `HF_TOKEN` from environment if no token provided
|
| 77 |
-
|
| 78 |
-
**Implementation:**
|
| 79 |
-
```python
|
| 80 |
-
effective_hf_token = oauth_token or settings.hf_token or settings.huggingface_api_key
|
| 81 |
-
hf_provider = HuggingFaceProvider(api_key=effective_hf_token)
|
| 82 |
-
```
|
| 83 |
-
|
| 84 |
-
### 5. MCP Tools (`src/mcp_tools.py`)
|
| 85 |
-
|
| 86 |
-
#### Image OCR Tool
|
| 87 |
-
- ✅ **Token Support**: `extract_text_from_image()` accepts `hf_token` parameter
|
| 88 |
-
- ✅ **Token Fallback**: Uses `settings.hf_token` or `settings.huggingface_api_key` if not provided
|
| 89 |
-
- ✅ **Service Integration**: Passes token to `ImageOCRService.extract_text()`
|
| 90 |
-
|
| 91 |
-
#### Audio Transcription Tool
|
| 92 |
-
- ✅ **Token Support**: `transcribe_audio_file()` accepts `hf_token` parameter
|
| 93 |
-
- ✅ **Token Fallback**: Uses `settings.hf_token` or `settings.huggingface_api_key` if not provided
|
| 94 |
-
- ✅ **Service Integration**: Passes token to `STTService.transcribe_file()`
|
| 95 |
-
|
| 96 |
-
## Token Flow Diagram
|
| 97 |
-
|
| 98 |
-
```
|
| 99 |
-
User Login (OAuth)
|
| 100 |
-
↓
|
| 101 |
-
oauth_token.token
|
| 102 |
-
↓
|
| 103 |
-
app.py: token_value
|
| 104 |
-
↓
|
| 105 |
-
┌─────────────────────────────────────┐
|
| 106 |
-
│ Service Layer │
|
| 107 |
-
├─────────────────────────────────────┤
|
| 108 |
-
│ MultimodalService │
|
| 109 |
-
│ ↓ hf_token=token_value │
|
| 110 |
-
│ AudioService │
|
| 111 |
-
│ ↓ hf_token=token_value │
|
| 112 |
-
│ STTService / ImageOCRService │
|
| 113 |
-
│ ↓ hf_token=token_value │
|
| 114 |
-
│ Gradio Client(hf_token=token) │
|
| 115 |
-
└─────────────────────────────────────┘
|
| 116 |
-
|
| 117 |
-
Alternative: Environment Variables
|
| 118 |
-
↓
|
| 119 |
-
HF_TOKEN or HUGGINGFACE_API_KEY
|
| 120 |
-
↓
|
| 121 |
-
settings.hf_token or settings.huggingface_api_key
|
| 122 |
-
↓
|
| 123 |
-
Same service flow as above
|
| 124 |
-
```
|
| 125 |
-
|
| 126 |
-
## Verification Checklist
|
| 127 |
-
|
| 128 |
-
- [x] STT Service accepts and uses `hf_token` parameter
|
| 129 |
-
- [x] Image OCR Service accepts and uses `hf_token` parameter
|
| 130 |
-
- [x] Audio Service passes token to STT service
|
| 131 |
-
- [x] Multimodal Service passes token to both audio and OCR services
|
| 132 |
-
- [x] App.py extracts OAuth token correctly
|
| 133 |
-
- [x] App.py passes token to multimodal service
|
| 134 |
-
- [x] HuggingFace API calls use token via `HuggingFaceProvider`
|
| 135 |
-
- [x] HuggingFace API calls use token via `InferenceClient`
|
| 136 |
-
- [x] MCP tools accept and use token parameter
|
| 137 |
-
- [x] Token priority is consistent: OAuth > Env Vars
|
| 138 |
-
- [x] Fallback to environment variables when OAuth not available
|
| 139 |
-
|
| 140 |
-
## Token Parameter Naming
|
| 141 |
-
|
| 142 |
-
All services consistently use `hf_token` parameter name:
|
| 143 |
-
- `STTService.transcribe_audio(..., hf_token=...)`
|
| 144 |
-
- `STTService.transcribe_file(..., hf_token=...)`
|
| 145 |
-
- `ImageOCRService.extract_text(..., hf_token=...)`
|
| 146 |
-
- `ImageOCRService.extract_text_from_image(..., hf_token=...)`
|
| 147 |
-
- `AudioService.process_audio_input(..., hf_token=...)`
|
| 148 |
-
- `MultimodalService.process_multimodal_input(..., hf_token=...)`
|
| 149 |
-
- `extract_text_from_image(..., hf_token=...)` (MCP tool)
|
| 150 |
-
- `transcribe_audio_file(..., hf_token=...)` (MCP tool)
|
| 151 |
-
|
| 152 |
-
## Gradio Client API Usage
|
| 153 |
-
|
| 154 |
-
According to Gradio documentation, the `Client` constructor accepts:
|
| 155 |
-
```python
|
| 156 |
-
Client(space_name, hf_token=None)
|
| 157 |
-
```
|
| 158 |
-
|
| 159 |
-
Our implementation correctly uses:
|
| 160 |
-
```python
|
| 161 |
-
Client(self.api_url, hf_token=token) # When token available
|
| 162 |
-
Client(self.api_url) # When no token (public Space)
|
| 163 |
-
```
|
| 164 |
-
|
| 165 |
-
## HuggingFace API Usage
|
| 166 |
-
|
| 167 |
-
### HuggingFaceProvider
|
| 168 |
-
```python
|
| 169 |
-
HuggingFaceProvider(api_key=effective_hf_token)
|
| 170 |
-
```
|
| 171 |
-
✅ Correctly passes token as `api_key` parameter
|
| 172 |
-
|
| 173 |
-
### InferenceClient
|
| 174 |
-
```python
|
| 175 |
-
InferenceClient(api_key=api_key) # When token provided
|
| 176 |
-
InferenceClient() # Falls back to HF_TOKEN env var
|
| 177 |
-
```
|
| 178 |
-
✅ Correctly passes token as `api_key` parameter
|
| 179 |
-
|
| 180 |
-
## Edge Cases Handled
|
| 181 |
-
|
| 182 |
-
1. **No Token Available**: Services work without token (public Gradio Spaces)
|
| 183 |
-
2. **Token Changes**: Client is recreated when token changes
|
| 184 |
-
3. **OAuth vs Env**: OAuth token takes priority over environment variables
|
| 185 |
-
4. **Multiple Token Sources**: Consistent priority across all services
|
| 186 |
-
5. **MCP Tools**: Support both explicit token and fallback to settings
|
| 187 |
-
|
| 188 |
-
## Recommendations
|
| 189 |
-
|
| 190 |
-
✅ **All implementations are correct and consistent**
|
| 191 |
-
|
| 192 |
-
The token authentication is properly implemented throughout:
|
| 193 |
-
- Gradio Client services accept and use tokens
|
| 194 |
-
- Service layer passes tokens through correctly
|
| 195 |
-
- Application layer extracts and passes OAuth tokens
|
| 196 |
-
- HuggingFace API calls use tokens via correct parameters
|
| 197 |
-
- MCP tools support token authentication
|
| 198 |
-
- Token priority is consistent across all layers
|
| 199 |
-
|
| 200 |
-
No changes needed - implementation follows best practices.
|
| 201 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation/TTS_MODAL_IMPLEMENTATION.md
DELETED
|
@@ -1,142 +0,0 @@
|
|
| 1 |
-
# TTS Modal GPU Implementation
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
The TTS (Text-to-Speech) service uses Kokoro 82M model running on Modal's GPU infrastructure. This document describes the implementation details and configuration.
|
| 6 |
-
|
| 7 |
-
## Implementation Details
|
| 8 |
-
|
| 9 |
-
### Modal GPU Function Pattern
|
| 10 |
-
|
| 11 |
-
The implementation follows Modal's recommended pattern for GPU functions:
|
| 12 |
-
|
| 13 |
-
1. **Module-Level Function Definition**: Modal functions must be defined at module level and attached to an app instance
|
| 14 |
-
2. **Lazy Initialization**: The function is set up on first use via `_setup_modal_function()`
|
| 15 |
-
3. **GPU Configuration**: GPU type is set at function definition time (requires app restart to change)
|
| 16 |
-
|
| 17 |
-
### Key Files
|
| 18 |
-
|
| 19 |
-
- `src/services/tts_modal.py` - Modal GPU executor for Kokoro TTS
|
| 20 |
-
- `src/services/audio_processing.py` - Unified audio service wrapper
|
| 21 |
-
- `src/utils/config.py` - Configuration settings
|
| 22 |
-
- `src/app.py` - UI integration with settings accordion
|
| 23 |
-
|
| 24 |
-
### Configuration Options
|
| 25 |
-
|
| 26 |
-
All TTS configuration is available in `src/utils/config.py`:
|
| 27 |
-
|
| 28 |
-
```python
|
| 29 |
-
tts_model: str = "hexgrad/Kokoro-82M" # Model ID
|
| 30 |
-
tts_voice: str = "af_heart" # Voice ID
|
| 31 |
-
tts_speed: float = 1.0 # Speed multiplier (0.5-2.0)
|
| 32 |
-
tts_gpu: str = "T4" # GPU type (T4, A10, A100, etc.)
|
| 33 |
-
tts_timeout: int = 60 # Timeout in seconds
|
| 34 |
-
enable_audio_output: bool = True # Enable/disable TTS
|
| 35 |
-
```
|
| 36 |
-
|
| 37 |
-
### UI Configuration
|
| 38 |
-
|
| 39 |
-
TTS settings are available in the Settings accordion:
|
| 40 |
-
|
| 41 |
-
- **Voice Dropdown**: Select from 20+ Kokoro voices (af_heart, af_bella, am_michael, etc.)
|
| 42 |
-
- **Speed Slider**: Adjust speech speed (0.5x to 2.0x)
|
| 43 |
-
- **GPU Dropdown**: Select GPU type (T4, A10, A100, L4, L40S) - visible only if Modal credentials configured
|
| 44 |
-
- **Enable Audio Output**: Toggle TTS generation
|
| 45 |
-
|
| 46 |
-
### Modal Function Implementation
|
| 47 |
-
|
| 48 |
-
The Modal GPU function is defined as:
|
| 49 |
-
|
| 50 |
-
```python
|
| 51 |
-
@app.function(
|
| 52 |
-
image=tts_image, # Image with Kokoro dependencies
|
| 53 |
-
gpu="T4", # GPU type (from settings.tts_gpu)
|
| 54 |
-
timeout=60, # Timeout (from settings.tts_timeout)
|
| 55 |
-
)
|
| 56 |
-
def kokoro_tts_function(text: str, voice: str, speed: float) -> tuple[int, np.ndarray]:
|
| 57 |
-
"""Modal GPU function for Kokoro TTS."""
|
| 58 |
-
from kokoro import KModel, KPipeline
|
| 59 |
-
import torch
|
| 60 |
-
|
| 61 |
-
model = KModel().to("cuda").eval()
|
| 62 |
-
pipeline = KPipeline(lang_code=voice[0])
|
| 63 |
-
pack = pipeline.load_voice(voice)
|
| 64 |
-
|
| 65 |
-
for _, ps, _ in pipeline(text, voice, speed):
|
| 66 |
-
ref_s = pack[len(ps) - 1]
|
| 67 |
-
audio = model(ps, ref_s, speed)
|
| 68 |
-
return (24000, audio.numpy())
|
| 69 |
-
```
|
| 70 |
-
|
| 71 |
-
### Usage Flow
|
| 72 |
-
|
| 73 |
-
1. User submits query with audio output enabled
|
| 74 |
-
2. Research agent processes query and generates text response
|
| 75 |
-
3. `AudioService.generate_audio_output()` is called with:
|
| 76 |
-
- Response text
|
| 77 |
-
- Voice (from UI dropdown or settings default)
|
| 78 |
-
- Speed (from UI slider or settings default)
|
| 79 |
-
4. `TTSService.synthesize_async()` calls Modal GPU function
|
| 80 |
-
5. Modal executes Kokoro TTS on GPU
|
| 81 |
-
6. Audio tuple `(sample_rate, audio_array)` is returned
|
| 82 |
-
7. Audio is displayed in Gradio Audio component
|
| 83 |
-
|
| 84 |
-
### Dependencies
|
| 85 |
-
|
| 86 |
-
Installed via `uv add --optional`:
|
| 87 |
-
- `gradio-client>=1.0.0` - For STT/OCR API calls
|
| 88 |
-
- `soundfile>=0.12.0` - For audio file I/O
|
| 89 |
-
- `Pillow>=10.0.0` - For image processing
|
| 90 |
-
|
| 91 |
-
Kokoro is installed in Modal image from source:
|
| 92 |
-
- `git+https://github.com/hexgrad/kokoro.git`
|
| 93 |
-
|
| 94 |
-
### GPU Types
|
| 95 |
-
|
| 96 |
-
Modal supports various GPU types:
|
| 97 |
-
- **T4**: Cheapest, good for testing (default)
|
| 98 |
-
- **A10**: Good balance of cost/performance
|
| 99 |
-
- **A100**: Fastest, most expensive
|
| 100 |
-
- **L4**: NVIDIA L4 GPU
|
| 101 |
-
- **L40S**: NVIDIA L40S GPU
|
| 102 |
-
|
| 103 |
-
**Note**: GPU type is set at function definition time. Changes to `settings.tts_gpu` require app restart.
|
| 104 |
-
|
| 105 |
-
### Error Handling
|
| 106 |
-
|
| 107 |
-
- If Modal credentials not configured: TTS service unavailable (graceful degradation)
|
| 108 |
-
- If Kokoro import fails: ConfigurationError raised
|
| 109 |
-
- If synthesis fails: Returns None, logs warning, continues without audio
|
| 110 |
-
- If GPU unavailable: Modal will queue or fail with clear error message
|
| 111 |
-
|
| 112 |
-
### Configuration Connection
|
| 113 |
-
|
| 114 |
-
1. **Settings → Implementation**: `settings.tts_voice`, `settings.tts_speed` used as defaults
|
| 115 |
-
2. **UI → Implementation**: UI dropdowns/sliders passed to `research_agent()` function
|
| 116 |
-
3. **Implementation → Modal**: Voice and speed passed to Modal GPU function
|
| 117 |
-
4. **GPU Configuration**: Set at function definition time (requires restart to change)
|
| 118 |
-
|
| 119 |
-
### Testing
|
| 120 |
-
|
| 121 |
-
To test TTS:
|
| 122 |
-
1. Ensure Modal credentials configured (`MODAL_TOKEN_ID`, `MODAL_TOKEN_SECRET`)
|
| 123 |
-
2. Enable audio output in settings
|
| 124 |
-
3. Submit a query
|
| 125 |
-
4. Check audio output component for generated speech
|
| 126 |
-
|
| 127 |
-
### References
|
| 128 |
-
|
| 129 |
-
- [Kokoro TTS Space](https://huggingface.co/spaces/hexgrad/Kokoro-TTS) - Reference implementation
|
| 130 |
-
- [Modal GPU Documentation](https://modal.com/docs/guide/gpu) - Modal GPU usage
|
| 131 |
-
- [Kokoro GitHub](https://github.com/hexgrad/kokoro) - Source code
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/index.md
CHANGED
|
@@ -30,8 +30,15 @@ The DETERMINATOR is a powerful generalist deep research agent system that uses i
|
|
| 30 |
## Quick Start
|
| 31 |
|
| 32 |
```bash
|
| 33 |
-
# Install uv if you haven't already
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
# Sync dependencies
|
| 37 |
uv sync
|
|
|
|
| 30 |
## Quick Start
|
| 31 |
|
| 32 |
```bash
|
| 33 |
+
# Install uv if you haven't already (recommended: standalone installer)
|
| 34 |
+
# Unix/macOS/Linux:
|
| 35 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 36 |
+
|
| 37 |
+
# Windows (PowerShell):
|
| 38 |
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
| 39 |
+
|
| 40 |
+
# Alternative: pipx install uv
|
| 41 |
+
# Or: pip install uv
|
| 42 |
|
| 43 |
# Sync dependencies
|
| 44 |
uv sync
|
docs/overview/architecture.md
CHANGED
|
@@ -134,10 +134,11 @@ The graph orchestrator (`src/orchestrator/graph_orchestrator.py`) implements a f
|
|
| 134 |
- **Research Flows**: Iterative and deep research patterns (`src/orchestrator/research_flow.py`)
|
| 135 |
- **Graph Builder**: Graph construction utilities (`src/agent_factory/graph_builder.py`)
|
| 136 |
- **Agents**: Pydantic AI agents (`src/agents/`, `src/agent_factory/agents.py`)
|
| 137 |
-
- **Search Tools**: PubMed, ClinicalTrials.gov, Europe PMC, RAG (`src/tools/`)
|
| 138 |
- **Judge Handler**: LLM-based evidence assessment (`src/agent_factory/judges.py`)
|
| 139 |
- **Embeddings**: Semantic search & deduplication (`src/services/embeddings.py`)
|
| 140 |
- **Statistical Analyzer**: Modal sandbox execution (`src/services/statistical_analyzer.py`)
|
|
|
|
| 141 |
- **Middleware**: State management, budget tracking, workflow coordination (`src/middleware/`)
|
| 142 |
- **MCP Tools**: Claude Desktop integration (`src/mcp_tools.py`)
|
| 143 |
- **Gradio UI**: Web interface with MCP server and streaming (`src/app.py`)
|
|
@@ -169,29 +170,25 @@ The system supports complex research workflows through:
|
|
| 169 |
|
| 170 |
- **Orchestrator Factory** (`src/orchestrator_factory.py`):
|
| 171 |
- Auto-detects mode: "advanced" if OpenAI key available, else "simple"
|
| 172 |
-
- Supports explicit mode selection: "simple", "magentic", "advanced"
|
| 173 |
- Lazy imports for optional dependencies
|
| 174 |
|
| 175 |
-
- **
|
| 176 |
-
- `
|
| 177 |
-
- `
|
| 178 |
-
- `
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
| 180 |
- **Execution Modes**:
|
| 181 |
- `use_graph=True`: Graph-based execution (parallel, conditional routing)
|
| 182 |
- `use_graph=False`: Agent chains (sequential, backward compatible)
|
| 183 |
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
|
| 197 |
|
|
|
|
| 134 |
- **Research Flows**: Iterative and deep research patterns (`src/orchestrator/research_flow.py`)
|
| 135 |
- **Graph Builder**: Graph construction utilities (`src/agent_factory/graph_builder.py`)
|
| 136 |
- **Agents**: Pydantic AI agents (`src/agents/`, `src/agent_factory/agents.py`)
|
| 137 |
+
- **Search Tools**: Neo4j knowledge graph, PubMed, ClinicalTrials.gov, Europe PMC, Web search, RAG (`src/tools/`)
|
| 138 |
- **Judge Handler**: LLM-based evidence assessment (`src/agent_factory/judges.py`)
|
| 139 |
- **Embeddings**: Semantic search & deduplication (`src/services/embeddings.py`)
|
| 140 |
- **Statistical Analyzer**: Modal sandbox execution (`src/services/statistical_analyzer.py`)
|
| 141 |
+
- **Multimodal Processing**: Image OCR and audio STT/TTS services (`src/services/multimodal_processing.py`, `src/services/audio_processing.py`)
|
| 142 |
- **Middleware**: State management, budget tracking, workflow coordination (`src/middleware/`)
|
| 143 |
- **MCP Tools**: Claude Desktop integration (`src/mcp_tools.py`)
|
| 144 |
- **Gradio UI**: Web interface with MCP server and streaming (`src/app.py`)
|
|
|
|
| 170 |
|
| 171 |
- **Orchestrator Factory** (`src/orchestrator_factory.py`):
|
| 172 |
- Auto-detects mode: "advanced" if OpenAI key available, else "simple"
|
| 173 |
+
- Supports explicit mode selection: "simple", "magentic" (alias for "advanced"), "advanced", "iterative", "deep", "auto"
|
| 174 |
- Lazy imports for optional dependencies
|
| 175 |
|
| 176 |
+
- **Orchestrator Modes** (selected in UI or via factory):
|
| 177 |
+
- `simple`: Legacy linear search-judge loop (Free Tier)
|
| 178 |
+
- `advanced` or `magentic`: Multi-agent coordination using Microsoft Agent Framework (requires OpenAI API key)
|
| 179 |
+
- `iterative`: Knowledge-gap-driven research with single loop (Free Tier)
|
| 180 |
+
- `deep`: Parallel section-based research with planning (Free Tier)
|
| 181 |
+
- `auto`: Intelligent mode detection based on query complexity (Free Tier)
|
| 182 |
+
|
| 183 |
+
- **Graph Research Modes** (used within graph orchestrator, separate from orchestrator mode):
|
| 184 |
+
- `iterative`: Single research loop pattern
|
| 185 |
+
- `deep`: Multi-section parallel research pattern
|
| 186 |
+
- `auto`: Auto-detect pattern based on query complexity
|
| 187 |
|
| 188 |
- **Execution Modes**:
|
| 189 |
- `use_graph=True`: Graph-based execution (parallel, conditional routing)
|
| 190 |
- `use_graph=False`: Agent chains (sequential, backward compatible)
|
| 191 |
|
| 192 |
+
**Note**: The UI provides separate controls for orchestrator mode and graph research mode. When using graph-based orchestrators (iterative/deep/auto), the graph research mode determines the specific pattern used within the graph execution.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
|
| 194 |
|
docs/overview/features.md
CHANGED
|
@@ -7,6 +7,7 @@ The DETERMINATOR provides a comprehensive set of features for AI-assisted resear
|
|
| 7 |
### Multi-Source Search
|
| 8 |
|
| 9 |
- **General Web Search**: Search general knowledge sources for any domain
|
|
|
|
| 10 |
- **PubMed**: Search peer-reviewed biomedical literature via NCBI E-utilities (automatically used when medical knowledge needed)
|
| 11 |
- **ClinicalTrials.gov**: Search interventional clinical trials (automatically used when medical knowledge needed)
|
| 12 |
- **Europe PMC**: Search preprints and peer-reviewed articles (includes bioRxiv/medRxiv)
|
|
@@ -21,9 +22,11 @@ The DETERMINATOR provides a comprehensive set of features for AI-assisted resear
|
|
| 21 |
|
| 22 |
### Authentication
|
| 23 |
|
| 24 |
-
- **
|
| 25 |
-
- **
|
| 26 |
-
- **
|
|
|
|
|
|
|
| 27 |
|
| 28 |
### Secure Code Execution
|
| 29 |
|
|
@@ -44,9 +47,25 @@ The DETERMINATOR provides a comprehensive set of features for AI-assisted resear
|
|
| 44 |
- **Parallel Research Loops**: Run multiple research tasks concurrently
|
| 45 |
- **Iterative Research**: Single-loop research with search-judge-synthesize cycles that continues until precise answers are found
|
| 46 |
- **Deep Research**: Multi-section parallel research with planning and synthesis
|
| 47 |
-
- **Magentic Orchestration**: Multi-agent coordination using Microsoft Agent Framework
|
| 48 |
- **Stops at Nothing**: Only stops at configured limits (budget, time, iterations), otherwise continues until finding precise answers
|
| 49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
### Real-Time Streaming
|
| 51 |
|
| 52 |
- **Event Streaming**: Real-time updates via `AsyncGenerator[AgentEvent]`
|
|
@@ -67,6 +86,16 @@ The DETERMINATOR provides a comprehensive set of features for AI-assisted resear
|
|
| 67 |
- **Conversation History**: Track iteration history and agent interactions
|
| 68 |
- **State Synchronization**: Share evidence across parallel loops
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
## Advanced Features
|
| 71 |
|
| 72 |
### Agent System
|
|
@@ -108,10 +137,12 @@ The DETERMINATOR provides a comprehensive set of features for AI-assisted resear
|
|
| 108 |
|
| 109 |
### Gradio Interface
|
| 110 |
|
| 111 |
-
- **Real-Time Chat**: Interactive chat interface
|
| 112 |
- **Streaming Updates**: Live progress updates
|
| 113 |
- **Accordion UI**: Organized display of pending/done operations
|
| 114 |
- **OAuth Integration**: Seamless HuggingFace authentication
|
|
|
|
|
|
|
| 115 |
|
| 116 |
### MCP Server
|
| 117 |
|
|
@@ -136,17 +167,3 @@ The DETERMINATOR provides a comprehensive set of features for AI-assisted resear
|
|
| 136 |
- **Architecture Diagrams**: Visual architecture documentation
|
| 137 |
- **API Reference**: Complete API documentation
|
| 138 |
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
|
|
|
| 7 |
### Multi-Source Search
|
| 8 |
|
| 9 |
- **General Web Search**: Search general knowledge sources for any domain
|
| 10 |
+
- **Neo4j Knowledge Graph**: Search structured knowledge graph for papers and disease relationships
|
| 11 |
- **PubMed**: Search peer-reviewed biomedical literature via NCBI E-utilities (automatically used when medical knowledge needed)
|
| 12 |
- **ClinicalTrials.gov**: Search interventional clinical trials (automatically used when medical knowledge needed)
|
| 13 |
- **Europe PMC**: Search preprints and peer-reviewed articles (includes bioRxiv/medRxiv)
|
|
|
|
| 22 |
|
| 23 |
### Authentication
|
| 24 |
|
| 25 |
+
- **REQUIRED**: Authentication is mandatory before using the application
|
| 26 |
+
- **HuggingFace OAuth**: Sign in with HuggingFace account for automatic API token usage (recommended)
|
| 27 |
+
- **Manual API Keys**: Support for HuggingFace API keys via environment variables (`HF_TOKEN` or `HUGGINGFACE_API_KEY`)
|
| 28 |
+
- **Free Tier Support**: Automatic fallback to HuggingFace Inference API (public models) when no API key is available
|
| 29 |
+
- **Authentication Check**: The application will display an error message if authentication is not provided
|
| 30 |
|
| 31 |
### Secure Code Execution
|
| 32 |
|
|
|
|
| 47 |
- **Parallel Research Loops**: Run multiple research tasks concurrently
|
| 48 |
- **Iterative Research**: Single-loop research with search-judge-synthesize cycles that continues until precise answers are found
|
| 49 |
- **Deep Research**: Multi-section parallel research with planning and synthesis
|
| 50 |
+
- **Magentic Orchestration**: Multi-agent coordination using Microsoft Agent Framework (alias: "advanced" mode)
|
| 51 |
- **Stops at Nothing**: Only stops at configured limits (budget, time, iterations), otherwise continues until finding precise answers
|
| 52 |
|
| 53 |
+
**Orchestrator Modes**:
|
| 54 |
+
- `simple`: Legacy linear search-judge loop
|
| 55 |
+
- `advanced` (or `magentic`): Multi-agent coordination (requires OpenAI API key)
|
| 56 |
+
- `iterative`: Knowledge-gap-driven research with single loop
|
| 57 |
+
- `deep`: Parallel section-based research with planning
|
| 58 |
+
- `auto`: Intelligent mode detection based on query complexity
|
| 59 |
+
|
| 60 |
+
**Graph Research Modes** (used within graph orchestrator):
|
| 61 |
+
- `iterative`: Single research loop pattern
|
| 62 |
+
- `deep`: Multi-section parallel research pattern
|
| 63 |
+
- `auto`: Auto-detect pattern based on query complexity
|
| 64 |
+
|
| 65 |
+
**Execution Modes**:
|
| 66 |
+
- `use_graph=True`: Graph-based execution with parallel and conditional routing
|
| 67 |
+
- `use_graph=False`: Agent chains with sequential execution (backward compatible)
|
| 68 |
+
|
| 69 |
### Real-Time Streaming
|
| 70 |
|
| 71 |
- **Event Streaming**: Real-time updates via `AsyncGenerator[AgentEvent]`
|
|
|
|
| 86 |
- **Conversation History**: Track iteration history and agent interactions
|
| 87 |
- **State Synchronization**: Share evidence across parallel loops
|
| 88 |
|
| 89 |
+
### Multimodal Input & Output
|
| 90 |
+
|
| 91 |
+
- **Image Input (OCR)**: Upload images and extract text using optical character recognition
|
| 92 |
+
- **Audio Input (STT)**: Record or upload audio files and transcribe to text using speech-to-text
|
| 93 |
+
- **Audio Output (TTS)**: Generate audio responses with text-to-speech synthesis
|
| 94 |
+
- **Configurable Settings**: Enable/disable multimodal features via sidebar settings
|
| 95 |
+
- **Voice Selection**: Choose from multiple TTS voices (American English: af_*, am_*)
|
| 96 |
+
- **Speech Speed Control**: Adjust TTS speech speed (0.5x to 2.0x)
|
| 97 |
+
- **Multimodal Processing Service**: Integrated service for processing images and audio files
|
| 98 |
+
|
| 99 |
## Advanced Features
|
| 100 |
|
| 101 |
### Agent System
|
|
|
|
| 137 |
|
| 138 |
### Gradio Interface
|
| 139 |
|
| 140 |
+
- **Real-Time Chat**: Interactive chat interface with multimodal support
|
| 141 |
- **Streaming Updates**: Live progress updates
|
| 142 |
- **Accordion UI**: Organized display of pending/done operations
|
| 143 |
- **OAuth Integration**: Seamless HuggingFace authentication
|
| 144 |
+
- **Multimodal Input**: Support for text, images, and audio input in the same interface
|
| 145 |
+
- **Sidebar Settings**: Configuration accordions for research, multimodal, and audio settings
|
| 146 |
|
| 147 |
### MCP Server
|
| 148 |
|
|
|
|
| 167 |
- **Architecture Diagrams**: Visual architecture documentation
|
| 168 |
- **API Reference**: Complete API documentation
|
| 169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/overview/quick-start.md
CHANGED
|
@@ -5,8 +5,15 @@ Get started with DeepCritical in minutes.
|
|
| 5 |
## Installation
|
| 6 |
|
| 7 |
```bash
|
| 8 |
-
# Install uv if you haven't already
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
# Sync dependencies
|
| 12 |
uv sync
|
|
@@ -23,21 +30,26 @@ Open your browser to `http://localhost:7860`.
|
|
| 23 |
|
| 24 |
## Basic Usage
|
| 25 |
|
| 26 |
-
### 1. Authentication (
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
**HuggingFace OAuth Login
|
| 29 |
- Click the "Sign in with HuggingFace" button at the top of the app
|
| 30 |
- Your HuggingFace API token will be automatically used for AI inference
|
| 31 |
- No need to manually enter API keys when logged in
|
| 32 |
|
| 33 |
-
**Manual API Key (
|
| 34 |
-
-
|
| 35 |
-
-
|
| 36 |
-
-
|
| 37 |
|
| 38 |
### 2. Start a Research Query
|
| 39 |
|
| 40 |
1. Enter your research question in the chat interface
|
|
|
|
|
|
|
|
|
|
| 41 |
2. Click "Submit" or press Enter
|
| 42 |
3. Watch the real-time progress as the system:
|
| 43 |
- Generates observations
|
|
@@ -46,6 +58,12 @@ Open your browser to `http://localhost:7860`.
|
|
| 46 |
- Evaluates evidence
|
| 47 |
- Synthesizes findings
|
| 48 |
4. Review the final research report
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
### 3. MCP Integration (Optional)
|
| 51 |
|
|
@@ -70,9 +88,12 @@ Connect DeepCritical to Claude Desktop:
|
|
| 70 |
- `search_pubmed`: Search peer-reviewed biomedical literature
|
| 71 |
- `search_clinical_trials`: Search ClinicalTrials.gov
|
| 72 |
- `search_biorxiv`: Search bioRxiv/medRxiv preprints
|
|
|
|
| 73 |
- `search_all`: Search all sources simultaneously
|
| 74 |
- `analyze_hypothesis`: Secure statistical analysis using Modal sandboxes
|
| 75 |
|
|
|
|
|
|
|
| 76 |
## Next Steps
|
| 77 |
|
| 78 |
- Read the [Installation Guide](../getting-started/installation.md) for detailed setup
|
|
|
|
| 5 |
## Installation
|
| 6 |
|
| 7 |
```bash
|
| 8 |
+
# Install uv if you haven't already (recommended: standalone installer)
|
| 9 |
+
# Unix/macOS/Linux:
|
| 10 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 11 |
+
|
| 12 |
+
# Windows (PowerShell):
|
| 13 |
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
| 14 |
+
|
| 15 |
+
# Alternative: pipx install uv
|
| 16 |
+
# Or: pip install uv
|
| 17 |
|
| 18 |
# Sync dependencies
|
| 19 |
uv sync
|
|
|
|
| 30 |
|
| 31 |
## Basic Usage
|
| 32 |
|
| 33 |
+
### 1. Authentication (REQUIRED)
|
| 34 |
+
|
| 35 |
+
**Authentication is mandatory** - you must authenticate before using the application. The app will display an error message if you try to use it without authentication.
|
| 36 |
|
| 37 |
+
**HuggingFace OAuth Login** (Recommended):
|
| 38 |
- Click the "Sign in with HuggingFace" button at the top of the app
|
| 39 |
- Your HuggingFace API token will be automatically used for AI inference
|
| 40 |
- No need to manually enter API keys when logged in
|
| 41 |
|
| 42 |
+
**Manual API Key** (Alternative):
|
| 43 |
+
- Set environment variable `HF_TOKEN` or `HUGGINGFACE_API_KEY` before starting the app
|
| 44 |
+
- The app will automatically use these tokens if OAuth login is not available
|
| 45 |
+
- Supports HuggingFace API keys only (OpenAI/Anthropic keys are not used in the current implementation)
|
| 46 |
|
| 47 |
### 2. Start a Research Query
|
| 48 |
|
| 49 |
1. Enter your research question in the chat interface
|
| 50 |
+
- **Text Input**: Type your question directly
|
| 51 |
+
- **Image Input**: Click the 📷 icon to upload images (OCR will extract text)
|
| 52 |
+
- **Audio Input**: Click the 🎤 icon to record or upload audio (STT will transcribe to text)
|
| 53 |
2. Click "Submit" or press Enter
|
| 54 |
3. Watch the real-time progress as the system:
|
| 55 |
- Generates observations
|
|
|
|
| 58 |
- Evaluates evidence
|
| 59 |
- Synthesizes findings
|
| 60 |
4. Review the final research report
|
| 61 |
+
- **Audio Output**: If enabled, the final response will include audio synthesis (TTS)
|
| 62 |
+
|
| 63 |
+
**Multimodal Features**:
|
| 64 |
+
- Configure image/audio input and output in the sidebar settings
|
| 65 |
+
- Image OCR and audio STT/TTS can be enabled/disabled independently
|
| 66 |
+
- TTS voice and speed can be customized in the Audio Output settings
|
| 67 |
|
| 68 |
### 3. MCP Integration (Optional)
|
| 69 |
|
|
|
|
| 88 |
- `search_pubmed`: Search peer-reviewed biomedical literature
|
| 89 |
- `search_clinical_trials`: Search ClinicalTrials.gov
|
| 90 |
- `search_biorxiv`: Search bioRxiv/medRxiv preprints
|
| 91 |
+
- `search_neo4j`: Search Neo4j knowledge graph for papers and disease relationships
|
| 92 |
- `search_all`: Search all sources simultaneously
|
| 93 |
- `analyze_hypothesis`: Secure statistical analysis using Modal sandboxes
|
| 94 |
|
| 95 |
+
**Note**: The application automatically uses all available search tools (Neo4j, PubMed, ClinicalTrials.gov, Europe PMC, Web search, RAG) based on query analysis. Neo4j knowledge graph search is included by default for biomedical queries.
|
| 96 |
+
|
| 97 |
## Next Steps
|
| 98 |
|
| 99 |
- Read the [Installation Guide](../getting-started/installation.md) for detailed setup
|
mkdocs.yml
CHANGED
|
@@ -88,7 +88,7 @@ nav:
|
|
| 88 |
- getting-started/mcp-integration.md
|
| 89 |
- getting-started/examples.md
|
| 90 |
- Configuration:
|
| 91 |
-
- configuration/
|
| 92 |
- Architecture:
|
| 93 |
- "Graph Orchestration": architecture/graph_orchestration.md
|
| 94 |
- "Workflow Diagrams": architecture/workflow-diagrams.md
|
|
|
|
| 88 |
- getting-started/mcp-integration.md
|
| 89 |
- getting-started/examples.md
|
| 90 |
- Configuration:
|
| 91 |
+
- configuration/index.md
|
| 92 |
- Architecture:
|
| 93 |
- "Graph Orchestration": architecture/graph_orchestration.md
|
| 94 |
- "Workflow Diagrams": architecture/workflow-diagrams.md
|
mkdocs.yml.enhanced
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
site_name: The DETERMINATOR
|
| 2 |
+
site_description: Generalist Deep Research Agent that Stops at Nothing
|
| 3 |
+
site_author: The DeepCritical Team
|
| 4 |
+
site_url: https://deepcritical.github.io/GradioDemo/
|
| 5 |
+
|
| 6 |
+
repo_name: DeepCritical/GradioDemo
|
| 7 |
+
repo_url: https://github.com/DeepCritical/GradioDemo
|
| 8 |
+
edit_uri: edit/dev/docs/
|
| 9 |
+
|
| 10 |
+
# Ensure all files are included even if not in nav
|
| 11 |
+
# strict: false
|
| 12 |
+
|
| 13 |
+
theme:
|
| 14 |
+
name: material
|
| 15 |
+
palette:
|
| 16 |
+
# Light mode
|
| 17 |
+
- scheme: default
|
| 18 |
+
primary: orange
|
| 19 |
+
accent: red
|
| 20 |
+
toggle:
|
| 21 |
+
icon: material/brightness-7
|
| 22 |
+
name: Switch to dark mode
|
| 23 |
+
# Dark mode
|
| 24 |
+
- scheme: slate
|
| 25 |
+
primary: orange
|
| 26 |
+
accent: red
|
| 27 |
+
toggle:
|
| 28 |
+
icon: material/brightness-4
|
| 29 |
+
name: Switch to light mode
|
| 30 |
+
features:
|
| 31 |
+
# Navigation features
|
| 32 |
+
- navigation.tabs
|
| 33 |
+
- navigation.sections
|
| 34 |
+
- navigation.expand
|
| 35 |
+
- navigation.top
|
| 36 |
+
- navigation.indexes
|
| 37 |
+
- navigation.instant
|
| 38 |
+
- navigation.tracking
|
| 39 |
+
- navigation.smooth
|
| 40 |
+
# Search features
|
| 41 |
+
- search.suggest
|
| 42 |
+
- search.highlight
|
| 43 |
+
# Content features
|
| 44 |
+
- content.code.annotate
|
| 45 |
+
- content.code.copy
|
| 46 |
+
- content.tabs.link
|
| 47 |
+
- content.tooltips
|
| 48 |
+
- toc.integrate
|
| 49 |
+
icon:
|
| 50 |
+
repo: fontawesome/brands/github
|
| 51 |
+
language: en
|
| 52 |
+
|
| 53 |
+
plugins:
|
| 54 |
+
- search:
|
| 55 |
+
lang:
|
| 56 |
+
- en
|
| 57 |
+
separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|&'
|
| 58 |
+
prebuild_index: true # Faster search initialization
|
| 59 |
+
indexing: full # Full-text indexing for better results
|
| 60 |
+
- mermaid2
|
| 61 |
+
- codeinclude
|
| 62 |
+
- git-revision-date-localized:
|
| 63 |
+
enable_creation_date: true
|
| 64 |
+
type: timeago # Shows "2 days ago" format
|
| 65 |
+
fallback_to_build_date: true
|
| 66 |
+
- minify:
|
| 67 |
+
minify_html: true
|
| 68 |
+
minify_js: true
|
| 69 |
+
minify_css: true
|
| 70 |
+
|
| 71 |
+
markdown_extensions:
|
| 72 |
+
- dev.docs_plugins:
|
| 73 |
+
base_path: "."
|
| 74 |
+
- pymdownx.highlight:
|
| 75 |
+
anchor_linenums: true
|
| 76 |
+
line_spans: __span # Allow line spans for highlighting
|
| 77 |
+
pygments_lang_class: true # Add language class to code blocks
|
| 78 |
+
use_pygments: true
|
| 79 |
+
noclasses: false # Use CSS classes for better theming
|
| 80 |
+
- pymdownx.inlinehilite
|
| 81 |
+
- pymdownx.superfences:
|
| 82 |
+
custom_fences:
|
| 83 |
+
- name: mermaid
|
| 84 |
+
class: mermaid
|
| 85 |
+
format: !!python/name:pymdownx.superfences.fence_code_format
|
| 86 |
+
preserve_tabs: true
|
| 87 |
+
- pymdownx.tabbed:
|
| 88 |
+
alternate_style: true
|
| 89 |
+
combine_header_slug: true # Better tab linking
|
| 90 |
+
- pymdownx.tasklist:
|
| 91 |
+
custom_checkbox: true
|
| 92 |
+
- pymdownx.emoji:
|
| 93 |
+
emoji_generator: !!python/name:pymdownx.emoji.to_svg
|
| 94 |
+
emoji_index: !!python/name:pymdownx.emoji.twemoji
|
| 95 |
+
- pymdownx.snippets
|
| 96 |
+
- admonition
|
| 97 |
+
- pymdownx.details
|
| 98 |
+
- attr_list
|
| 99 |
+
- md_in_html
|
| 100 |
+
- tables
|
| 101 |
+
- meta # Frontmatter support for tags, categories, etc.
|
| 102 |
+
- toc:
|
| 103 |
+
permalink: true
|
| 104 |
+
permalink_title: "Anchor link to this section"
|
| 105 |
+
baselevel: 1
|
| 106 |
+
toc_depth: 3
|
| 107 |
+
slugify: !!python/object/apply:pymdownx.slugs.slugify
|
| 108 |
+
kwds:
|
| 109 |
+
case: lower
|
| 110 |
+
|
| 111 |
+
nav:
|
| 112 |
+
- Home: index.md
|
| 113 |
+
- Overview:
|
| 114 |
+
- overview/architecture.md
|
| 115 |
+
- overview/features.md
|
| 116 |
+
- Getting Started:
|
| 117 |
+
- getting-started/installation.md
|
| 118 |
+
- getting-started/quick-start.md
|
| 119 |
+
- getting-started/mcp-integration.md
|
| 120 |
+
- getting-started/examples.md
|
| 121 |
+
- Configuration:
|
| 122 |
+
- configuration/index.md
|
| 123 |
+
- Architecture:
|
| 124 |
+
- "Graph Orchestration": architecture/graph_orchestration.md
|
| 125 |
+
- "Workflow Diagrams": architecture/workflow-diagrams.md
|
| 126 |
+
- "Agents": architecture/agents.md
|
| 127 |
+
- "Orchestrators": architecture/orchestrators.md
|
| 128 |
+
- "Tools": architecture/tools.md
|
| 129 |
+
- "Middleware": architecture/middleware.md
|
| 130 |
+
- "Services": architecture/services.md
|
| 131 |
+
- API Reference:
|
| 132 |
+
- api/agents.md
|
| 133 |
+
- api/tools.md
|
| 134 |
+
- api/orchestrators.md
|
| 135 |
+
- api/services.md
|
| 136 |
+
- api/models.md
|
| 137 |
+
- Contributing:
|
| 138 |
+
- contributing/index.md
|
| 139 |
+
- contributing/code-quality.md
|
| 140 |
+
- contributing/code-style.md
|
| 141 |
+
- contributing/error-handling.md
|
| 142 |
+
- contributing/implementation-patterns.md
|
| 143 |
+
- contributing/prompt-engineering.md
|
| 144 |
+
- contributing/testing.md
|
| 145 |
+
- License: LICENSE.md
|
| 146 |
+
- Team: team.md
|
| 147 |
+
|
| 148 |
+
extra:
|
| 149 |
+
social:
|
| 150 |
+
- icon: fontawesome/brands/github
|
| 151 |
+
link: https://github.com/DeepCritical/GradioDemo
|
| 152 |
+
name: GitHub
|
| 153 |
+
- icon: fontawesome/brands/twitter
|
| 154 |
+
link: https://twitter.com/josephpollack
|
| 155 |
+
name: Twitter
|
| 156 |
+
- icon: material/web
|
| 157 |
+
link: https://huggingface.co/spaces/DataQuests/DeepCritical
|
| 158 |
+
name: Live Demo
|
| 159 |
+
- icon: fontawesome/brands/discord
|
| 160 |
+
link: https://discord.gg/n8ytYeh25n
|
| 161 |
+
name: Discord
|
| 162 |
+
generator:
|
| 163 |
+
enabled: false # Hide generator meta tag
|
| 164 |
+
|
| 165 |
+
copyright: Copyright © 2024 DeepCritical Team
|
| 166 |
+
|