Spaces:
Sleeping
feat: consolidate documentation and improve code organization
Browse files- Consolidate all documentation into single comprehensive README.md
* Features, setup, deployment, and configuration
* Architecture overview and tech stack
* Quick start guide with examples
* Recent updates (URL handling fix)
- Create DEPRECATED.md noting consolidated files
* Lists all deprecated documentation
* Provides migration guide for developers
* References for historical context
- Enhance context_builder.py for complete URL handling
* Always provides full HTTPS URLs (no relative paths)
* Includes contact information with every context
* Properly processes all snapshot sections
* Well-documented with usage examples
- Keep single source of truth (README.md)
* Easier to maintain
* Better for onboarding
* Clear deprecation path
* Reference to code for implementation details
Key improvements:
✓ Consolidated 20+ docs into one clear README
✓ All URLs are complete HTTPS (not /relative/paths)
✓ Contact info always included (email, phone, hours)
✓ 28 snapshot JSONs as authoritative source
✓ Clear migration path for developers
See README.md for full documentation.
See DEPRECATED.md for consolidated files.
🤖 Generated with Claude Code
- DEPRECATED.md +103 -0
- README.md +341 -6
- src/analyzer/context_builder.py +49 -15
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Deprecated Documentation
|
| 2 |
+
|
| 3 |
+
This file lists documentation that has been consolidated into the main [README.md](README.md).
|
| 4 |
+
|
| 5 |
+
## Deprecated Files
|
| 6 |
+
|
| 7 |
+
All information from these files has been consolidated into the main README. They are kept for historical reference but should not be used for current development.
|
| 8 |
+
|
| 9 |
+
### Documentation Files (Deprecated)
|
| 10 |
+
- `FEATURES.md` - Use [README.md](README.md) instead
|
| 11 |
+
- `DEPLOYMENT.md` - Use [README.md](README.md) instead
|
| 12 |
+
- `LOGGING.md` - Use [README.md](README.md) instead
|
| 13 |
+
- `TECHNICAL_REFERENCE.md` - Use [README.md](README.md) and code comments
|
| 14 |
+
- `DOCS.md` - Use [README.md](README.md) instead
|
| 15 |
+
- `QUICK_START_IMPROVEMENTS.md` - Use [README.md](README.md) instead
|
| 16 |
+
|
| 17 |
+
### Issue/Fix Documents (Deprecated)
|
| 18 |
+
- `COMPANY_ANALYSIS_FEATURE.md` - Feature is now in main codebase
|
| 19 |
+
- `COMPLETE_FIX_ALL_HANDLERS.md` - Issues have been resolved
|
| 20 |
+
- `CRITICAL_FIX_LIST_LIMIT.md` - Issues have been resolved
|
| 21 |
+
- `FINAL_BUG_FIX_SUMMARY.md` - Issues have been resolved
|
| 22 |
+
- `FIX_HUGGINGFACE_DEPLOYMENT.md` - Deployment process is in README
|
| 23 |
+
- `GIT_LFS_SETUP.md` - Use standard git setup
|
| 24 |
+
- `IMPROVEMENTS_IMPLEMENTED.md` - Improvements are in current code
|
| 25 |
+
- `IMPLEMENTATION_SUMMARY.txt` - See current code implementation
|
| 26 |
+
|
| 27 |
+
### Parsing/Data Files (Deprecated)
|
| 28 |
+
- `GRANT_JSON_PARSING_SUMMARY.md` - Parsing is automated; see context_builder.py
|
| 29 |
+
- `PARSING_REPORT.md` - Parsing is automated; see context_builder.py
|
| 30 |
+
|
| 31 |
+
### URL Handling (Consolidated)
|
| 32 |
+
The following URL handling files have been consolidated:
|
| 33 |
+
- `URL_HANDLING_GUIDE.md` - See `src/analyzer/context_builder.py` and README.md
|
| 34 |
+
- `URL_USAGE_EXAMPLES.md` - See `src/analyzer/context_builder.py`
|
| 35 |
+
- `URL_FIX_COMPLETE.md` - See README.md "Recent Updates" section
|
| 36 |
+
- `URLS_FIXED_SUMMARY.txt` - See README.md "Recent Updates" section
|
| 37 |
+
- `SOLUTION_SUMMARY.md` - See README.md "Recent Updates" section
|
| 38 |
+
|
| 39 |
+
---
|
| 40 |
+
|
| 41 |
+
## Key Points
|
| 42 |
+
|
| 43 |
+
1. **All essential information is now in README.md**
|
| 44 |
+
- Features, setup, deployment, configuration
|
| 45 |
+
- Quick start guide
|
| 46 |
+
- Architecture overview
|
| 47 |
+
|
| 48 |
+
2. **Code comments and docstrings are primary reference**
|
| 49 |
+
- Implementation details are in the code
|
| 50 |
+
- See individual module files for specifics
|
| 51 |
+
|
| 52 |
+
3. **URL Handling is Standardized**
|
| 53 |
+
- All URLs are complete HTTPS URLs
|
| 54 |
+
- See `src/analyzer/context_builder.py`
|
| 55 |
+
- Contact: support@iuk.ukri.org / 0300 321 4357
|
| 56 |
+
|
| 57 |
+
4. **Data Source is Authoritative**
|
| 58 |
+
- `data/snapshots/` contains all grant information
|
| 59 |
+
- `context_builder.py` processes it correctly
|
| 60 |
+
- No need for additional documentation
|
| 61 |
+
|
| 62 |
+
---
|
| 63 |
+
|
| 64 |
+
## Reference for Historical Context
|
| 65 |
+
|
| 66 |
+
If you need to understand historical issues or design decisions, these files provide that context:
|
| 67 |
+
- This file lists what was deprecated and why
|
| 68 |
+
- The git history contains all previous changes
|
| 69 |
+
- Code comments explain implementation choices
|
| 70 |
+
|
| 71 |
+
---
|
| 72 |
+
|
| 73 |
+
## Migration Guide
|
| 74 |
+
|
| 75 |
+
### If you were using FEATURES.md
|
| 76 |
+
→ See README.md "Features" section
|
| 77 |
+
|
| 78 |
+
### If you were using DEPLOYMENT.md
|
| 79 |
+
→ See README.md "Deployment" section
|
| 80 |
+
|
| 81 |
+
### If you were using LOGGING.md
|
| 82 |
+
→ See README.md "Query Logging & RLHF" section
|
| 83 |
+
|
| 84 |
+
### If you were using URL_HANDLING_GUIDE.md
|
| 85 |
+
→ See `src/analyzer/context_builder.py` code
|
| 86 |
+
→ All URLs are complete HTTPS in context output
|
| 87 |
+
|
| 88 |
+
### If you were looking for quick start
|
| 89 |
+
→ See README.md "Quick Start" section
|
| 90 |
+
|
| 91 |
+
---
|
| 92 |
+
|
| 93 |
+
## Questions?
|
| 94 |
+
|
| 95 |
+
- Check README.md first
|
| 96 |
+
- Look at the relevant source code file
|
| 97 |
+
- Review git history for context on changes
|
| 98 |
+
- Refer to code docstrings and comments
|
| 99 |
+
|
| 100 |
+
---
|
| 101 |
+
|
| 102 |
+
**Last Updated**: October 24, 2025
|
| 103 |
+
**Consolidation Reason**: Improve maintainability by having single source of truth (README.md)
|
|
@@ -1,10 +1,345 @@
|
|
| 1 |
-
# Grant Analyst
|
| 2 |
|
| 3 |
-
|
| 4 |
|
| 5 |
-
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
```bash
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Grant Analyst
|
| 2 |
|
| 3 |
+
**AI-powered grant discovery and analysis for Innovate UK funding opportunities**
|
| 4 |
|
| 5 |
+
Intelligent grant search with natural language understanding, company website analysis, and automated recommendations.
|
| 6 |
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
## 🚀 Features
|
| 10 |
+
|
| 11 |
+
### Core Capabilities
|
| 12 |
+
- 🔍 **Natural Language Search** - Ask questions in plain English
|
| 13 |
+
- 🌐 **Company Website Analysis** - Paste any URL to get grant recommendations
|
| 14 |
+
- 📊 **Grant Comparisons** - Side-by-side analysis of funding opportunities
|
| 15 |
+
- 📅 **Deadline Tracking** - Never miss an opportunity
|
| 16 |
+
- 🎯 **Smart Matching** - AI-powered eligibility and fit analysis
|
| 17 |
+
- 📝 **Query Logging** - Automatic logging for RLHF training
|
| 18 |
+
|
| 19 |
+
### What Makes It Special
|
| 20 |
+
- **LLM-powered** - Uses GPT-4 for intelligent understanding
|
| 21 |
+
- **Function calling** - Automatically selects the right tools
|
| 22 |
+
- **Web scraping** - Fetches and analyzes company websites
|
| 23 |
+
- **No manual work** - Everything happens automatically
|
| 24 |
+
- **Client-ready** - Beautiful Gradio interface with preset questions
|
| 25 |
+
|
| 26 |
+
---
|
| 27 |
+
|
| 28 |
+
## 📖 Quick Start
|
| 29 |
+
|
| 30 |
+
### 1. Installation
|
| 31 |
+
|
| 32 |
+
```bash
|
| 33 |
+
# Clone repository
|
| 34 |
+
git clone https://github.com/your-username/grant-analyst.git
|
| 35 |
+
cd grant-analyst
|
| 36 |
+
|
| 37 |
+
# Install dependencies
|
| 38 |
+
pip install -r requirements.txt
|
| 39 |
+
|
| 40 |
+
# Set API key
|
| 41 |
+
export OPENAI_API_KEY=your-key-here
|
| 42 |
+
```
|
| 43 |
+
|
| 44 |
+
### 2. Run Locally
|
| 45 |
+
|
| 46 |
+
```bash
|
| 47 |
+
# Web interface (recommended)
|
| 48 |
+
python -m src.analyzer.chat.demo_app
|
| 49 |
+
|
| 50 |
+
# CLI chat
|
| 51 |
+
python -m src.analyzer.chat.run_chat_llm
|
| 52 |
+
|
| 53 |
+
# Or use the entry point
|
| 54 |
+
python app.py
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
Open browser to `http://localhost:7860`
|
| 58 |
+
|
| 59 |
+
### 3. Try It Out
|
| 60 |
+
|
| 61 |
+
**Natural language queries:**
|
| 62 |
+
```
|
| 63 |
+
"What grants are available for battery innovation?"
|
| 64 |
+
"Show me grants for SMEs over £100k"
|
| 65 |
+
"When do the feasibility study grants close?"
|
| 66 |
+
```
|
| 67 |
+
|
| 68 |
+
**Company analysis:**
|
| 69 |
+
```
|
| 70 |
+
"What grants would be suitable for https://northvolt.com?"
|
| 71 |
+
"Analyze www.graphcore.ai and recommend grants"
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
**Comparisons:**
|
| 75 |
+
```
|
| 76 |
+
"Compare competition-2313 and competition-2314"
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
---
|
| 80 |
+
|
| 81 |
+
## 🌐 Company Website Analysis
|
| 82 |
+
|
| 83 |
+
### How It Works
|
| 84 |
+
1. **User provides URL** - "What grants for https://company.com?"
|
| 85 |
+
2. **System fetches site** - Extracts text content intelligently
|
| 86 |
+
3. **AI analyzes** - Understands industry, activities, needs
|
| 87 |
+
4. **Matches grants** - Recommends top 3 most relevant
|
| 88 |
+
5. **Explains why** - Provides reasoning for each match
|
| 89 |
+
|
| 90 |
+
### Real Examples
|
| 91 |
+
|
| 92 |
+
**Northvolt (Battery Company)**
|
| 93 |
+
```
|
| 94 |
+
Input: https://northvolt.com
|
| 95 |
+
Output:
|
| 96 |
+
- Battery Innovation Feasibility Studies
|
| 97 |
+
- Resource efficiency for sustainability
|
| 98 |
+
- Innovation Loans Round 23
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
**Graphcore (AI Hardware)**
|
| 102 |
+
```
|
| 103 |
+
Input: https://graphcore.ai
|
| 104 |
+
Output:
|
| 105 |
+
- Innovation Loans Round 23
|
| 106 |
+
- DRIVE35 Scale-up Fund
|
| 107 |
+
- Horizon Europe Guarantee Extension
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
---
|
| 111 |
+
|
| 112 |
+
## 🎯 Example Use Cases
|
| 113 |
+
|
| 114 |
+
### 1. Grant Advisory
|
| 115 |
+
**Scenario:** Client asks what grants fit their business
|
| 116 |
+
|
| 117 |
+
**Old way:** Manually research company, read all grants, match by hand
|
| 118 |
+
**New way:** `"What grants for https://client-company.com?"`
|
| 119 |
+
**Result:** Instant recommendations with reasoning!
|
| 120 |
+
|
| 121 |
+
### 2. Lead Qualification
|
| 122 |
+
**Scenario:** Prospecting companies for grant applications
|
| 123 |
+
|
| 124 |
+
**Old way:** Visit website, understand business, search database
|
| 125 |
+
**New way:** Paste URL into chat
|
| 126 |
+
**Result:** Know immediately if they're a good fit!
|
| 127 |
+
|
| 128 |
+
### 3. Client Demos
|
| 129 |
+
**Scenario:** Show prospects how the system works
|
| 130 |
+
|
| 131 |
+
**Old way:** Hope your queries work during the demo
|
| 132 |
+
**New way:** Use 5 preset questions guaranteed to work
|
| 133 |
+
**Result:** Professional, reliable demonstrations!
|
| 134 |
+
|
| 135 |
+
---
|
| 136 |
+
|
| 137 |
+
## 📊 Query Logging & RLHF
|
| 138 |
+
|
| 139 |
+
### Automatic Logging
|
| 140 |
+
Every user interaction is logged automatically:
|
| 141 |
+
- ✅ User query
|
| 142 |
+
- ✅ AI response
|
| 143 |
+
- ✅ Tools used
|
| 144 |
+
- ✅ Response time
|
| 145 |
+
- ✅ Success/failure
|
| 146 |
+
- ✅ Timestamp
|
| 147 |
+
|
| 148 |
+
### Export for Training
|
| 149 |
```bash
|
| 150 |
+
# View statistics
|
| 151 |
+
python export_logs.py --stats
|
| 152 |
+
|
| 153 |
+
# Export to Excel
|
| 154 |
+
python export_logs.py --format excel
|
| 155 |
+
|
| 156 |
+
# Export for RLHF
|
| 157 |
+
python export_logs.py --format rlhf
|
| 158 |
+
```
|
| 159 |
+
|
| 160 |
+
### Use Cases
|
| 161 |
+
- **RLHF training** - Fine-tune models on real usage
|
| 162 |
+
- **Analytics** - Understand user patterns
|
| 163 |
+
- **Quality control** - Find and fix issues
|
| 164 |
+
- **Product improvement** - Identify missing features
|
| 165 |
+
|
| 166 |
+
---
|
| 167 |
+
|
| 168 |
+
## 🚀 Deployment
|
| 169 |
+
|
| 170 |
+
### Deploy to Hugging Face Spaces
|
| 171 |
+
|
| 172 |
+
```bash
|
| 173 |
+
# Use the deployment package
|
| 174 |
+
cd ~/grant-analyst-deploy
|
| 175 |
+
gradio deploy
|
| 176 |
+
```
|
| 177 |
+
|
| 178 |
+
**When prompted:**
|
| 179 |
+
- App file: `app.py`
|
| 180 |
+
- Space visibility: `public`
|
| 181 |
+
|
| 182 |
+
**After deployment:**
|
| 183 |
+
1. Set `OPENAI_API_KEY` in Space secrets
|
| 184 |
+
2. Wait ~2 min for startup
|
| 185 |
+
3. Test with company URL!
|
| 186 |
+
|
| 187 |
+
### Deploy Requirements
|
| 188 |
+
- Python 3.10+
|
| 189 |
+
- OpenAI API key
|
| 190 |
+
- 28 grant JSON files (~1.8MB)
|
| 191 |
+
- No GPU needed (CPU is fine!)
|
| 192 |
+
|
| 193 |
+
---
|
| 194 |
+
|
| 195 |
+
## 🛠️ Architecture
|
| 196 |
+
|
| 197 |
+
```
|
| 198 |
+
grant-analyst/
|
| 199 |
+
├── src/analyzer/
|
| 200 |
+
│ ├── chat/
|
| 201 |
+
│ │ ├── demo_app.py # Gradio web interface
|
| 202 |
+
│ │ ├── chat_tools.py # Core functionality + web scraping
|
| 203 |
+
│ │ ├── tool_schemas.py # LLM function calling schemas
|
| 204 |
+
│ │ ├── run_chat_llm.py # CLI interface
|
| 205 |
+
│ │ └── run_chat.py # Alternative chat interface
|
| 206 |
+
│ ├── search/
|
| 207 |
+
│ │ └── hybrid_index.py # Search indexing
|
| 208 |
+
│ ├── utils/
|
| 209 |
+
│ │ ├── query_logger.py # Automatic logging
|
| 210 |
+
│ │ ├── dates.py # Date parsing utilities
|
| 211 |
+
│ │ └── errors.py # Error handling
|
| 212 |
+
│ ├── context_builder.py # Context generation with full URLs
|
| 213 |
+
│ ├── data_loader.py # Grant data loading
|
| 214 |
+
│ ├── llm_client.py # OpenAI/Anthropic client
|
| 215 |
+
│ └── config.py # Configuration
|
| 216 |
+
├── data/
|
| 217 |
+
│ ├── snapshots/ # 28 grant JSON files (source of truth)
|
| 218 |
+
│ └── supporting/ # Additional documentation
|
| 219 |
+
├── context/
|
| 220 |
+
│ ├── grants/ # Per-grant extracted info
|
| 221 |
+
│ └── general/ # Standard Innovate UK info
|
| 222 |
+
├── app.py # Entry point
|
| 223 |
+
└── requirements.txt # Dependencies
|
| 224 |
+
```
|
| 225 |
+
|
| 226 |
+
---
|
| 227 |
+
|
| 228 |
+
## 🔧 Configuration
|
| 229 |
+
|
| 230 |
+
### Environment Variables
|
| 231 |
+
```bash
|
| 232 |
+
# Required
|
| 233 |
+
export OPENAI_API_KEY=sk-...
|
| 234 |
+
|
| 235 |
+
# Optional
|
| 236 |
+
export ANTHROPIC_API_KEY=sk-ant-...
|
| 237 |
+
export ENABLE_EXTENDED_TOOLS=1 # Enable advanced features
|
| 238 |
+
```
|
| 239 |
+
|
| 240 |
+
### Config File
|
| 241 |
+
Edit `src/analyzer/config.py` for:
|
| 242 |
+
- Default model selection
|
| 243 |
+
- Temperature settings
|
| 244 |
+
- Max tokens
|
| 245 |
+
- Search parameters
|
| 246 |
+
|
| 247 |
+
---
|
| 248 |
+
|
| 249 |
+
## 📈 Tech Stack
|
| 250 |
+
|
| 251 |
+
- **UI**: Gradio 4.0+
|
| 252 |
+
- **LLM**: OpenAI GPT-4 (or Anthropic Claude)
|
| 253 |
+
- **Search**: Hybrid TF-IDF + semantic
|
| 254 |
+
- **Parsing**: Custom HTML parser
|
| 255 |
+
- **Data**: 28 Innovate UK grants
|
| 256 |
+
- **Logging**: CSV + JSONL formats
|
| 257 |
+
|
| 258 |
+
---
|
| 259 |
+
|
| 260 |
+
## 📚 Documentation
|
| 261 |
+
|
| 262 |
+
### Quick References
|
| 263 |
+
- **URL Handling** - URLs are always provided in complete `https://` form (see context_builder.py)
|
| 264 |
+
- **Data Sources** - Snapshot JSONs contain authoritative grant information
|
| 265 |
+
- **Contact Info** - support@iuk.ukri.org / 0300 321 4357 / 9am-12pm, 2pm-5pm Mon-Fri
|
| 266 |
+
|
| 267 |
+
### Key Files
|
| 268 |
+
- `src/analyzer/context_builder.py` - Context generation (provides full URLs)
|
| 269 |
+
- `src/analyzer/chat/chat_tools.py` - Core tool implementations
|
| 270 |
+
- `data/snapshots/` - 28 grant JSON files with complete grant data
|
| 271 |
+
- `context/grants/` - Extracted per-grant information
|
| 272 |
+
- `context/general/info.json` - Standard Innovate UK information
|
| 273 |
+
|
| 274 |
+
---
|
| 275 |
+
|
| 276 |
+
## 🔄 Recent Updates
|
| 277 |
+
|
| 278 |
+
### URL Handling Fix (Latest)
|
| 279 |
+
- ✅ All URLs provided in complete `https://` form
|
| 280 |
+
- ✅ No relative paths (`/info/contact` → `https://apply-for-innovation-funding.service.gov.uk/info/contact`)
|
| 281 |
+
- ✅ Contact information always included (email, phone, hours)
|
| 282 |
+
- ✅ See `src/analyzer/context_builder.py` for implementation
|
| 283 |
+
|
| 284 |
+
### Data Organization
|
| 285 |
+
- ✅ 28 snapshot JSONs as authoritative source
|
| 286 |
+
- ✅ Per-grant context files for quick access
|
| 287 |
+
- ✅ General info file with standard links
|
| 288 |
+
- ✅ Proper context generation for LLM consumption
|
| 289 |
+
|
| 290 |
+
---
|
| 291 |
+
|
| 292 |
+
## 🎯 Roadmap
|
| 293 |
+
|
| 294 |
+
### Current Features (✅)
|
| 295 |
+
- Natural language search
|
| 296 |
+
- Company website analysis
|
| 297 |
+
- Grant comparisons
|
| 298 |
+
- Query logging
|
| 299 |
+
- Gradio demo interface
|
| 300 |
+
- Complete URL delivery to model
|
| 301 |
+
- Per-grant extracted information
|
| 302 |
+
|
| 303 |
+
### Coming Soon (🔜)
|
| 304 |
+
- Multi-page website scraping
|
| 305 |
+
- PDF document analysis
|
| 306 |
+
- Batch company analysis
|
| 307 |
+
- Confidence scores
|
| 308 |
+
- Advanced analytics dashboard
|
| 309 |
+
|
| 310 |
+
---
|
| 311 |
+
|
| 312 |
+
## 🤝 Contributing
|
| 313 |
+
|
| 314 |
+
We welcome contributions! Areas for improvement:
|
| 315 |
+
- Performance optimizations
|
| 316 |
+
- Additional grant sources
|
| 317 |
+
- Enhanced company analysis
|
| 318 |
+
- Better error handling
|
| 319 |
+
- More comprehensive tests
|
| 320 |
+
|
| 321 |
+
---
|
| 322 |
+
|
| 323 |
+
## 📝 License
|
| 324 |
+
|
| 325 |
+
This project is licensed under the MIT License - see [LICENSE](LICENSE) file for details.
|
| 326 |
+
|
| 327 |
+
---
|
| 328 |
+
|
| 329 |
+
## 🙏 Acknowledgments
|
| 330 |
+
|
| 331 |
+
- **Innovate UK** - Grant data source
|
| 332 |
+
- **OpenAI** - GPT-4 API
|
| 333 |
+
- **Gradio** - Beautiful UI framework
|
| 334 |
+
- **Anthropic** - Claude API support
|
| 335 |
+
|
| 336 |
+
---
|
| 337 |
+
|
| 338 |
+
## 📞 Support
|
| 339 |
+
|
| 340 |
+
- **Issues**: [GitHub Issues](https://github.com/your-username/grant-analyst/issues)
|
| 341 |
+
- **Email**: your-email@example.com
|
| 342 |
+
|
| 343 |
+
---
|
| 344 |
+
|
| 345 |
+
**Built with ❤️ for the grant-seeking community**
|
|
@@ -32,7 +32,12 @@ def _maybe(k: str, v: Any) -> str:
|
|
| 32 |
# ----------------------------- Context builder --------------------------------
|
| 33 |
|
| 34 |
def build_context(grant: Dict[str, Any], past_winners: Optional[List[Dict[str, Any]]] = None) -> str:
|
| 35 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
lines: List[str] = []
|
| 37 |
|
| 38 |
# --- Basic info ---
|
|
@@ -40,38 +45,67 @@ def build_context(grant: Dict[str, Any], past_winners: Optional[List[Dict[str, A
|
|
| 40 |
if title:
|
| 41 |
lines.append(f"TITLE: {_clean(title)}")
|
| 42 |
|
|
|
|
| 43 |
url = grant.get("url") or grant.get("link")
|
| 44 |
if url:
|
| 45 |
-
lines.append(f"URL: {url}")
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
-
|
|
|
|
| 52 |
if deadline:
|
| 53 |
lines.append(f"DEADLINE: {_clean(deadline)}")
|
| 54 |
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
sections = grant.get("sections") or {}
|
| 57 |
if sections:
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
else:
|
| 62 |
-
#
|
| 63 |
desc = grant.get("description") or grant.get("summary") or grant.get("scope")
|
| 64 |
if desc:
|
| 65 |
-
lines.append(f"
|
| 66 |
|
| 67 |
# --- Optional extras ---
|
| 68 |
eligibility = grant.get("eligibility")
|
| 69 |
if eligibility:
|
| 70 |
-
lines.append(f"
|
| 71 |
|
| 72 |
scope = grant.get("scope")
|
| 73 |
if scope:
|
| 74 |
-
lines.append(f"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
|
| 76 |
# --- Past winners summary ---
|
| 77 |
if past_winners:
|
|
|
|
| 32 |
# ----------------------------- Context builder --------------------------------
|
| 33 |
|
| 34 |
def build_context(grant: Dict[str, Any], past_winners: Optional[List[Dict[str, Any]]] = None) -> str:
|
| 35 |
+
"""
|
| 36 |
+
Flatten a grant JSON object + optional past winners into a readable context string.
|
| 37 |
+
|
| 38 |
+
CRITICAL: All URLs are provided in FULL form (https://...), never partial paths.
|
| 39 |
+
The model receives complete, actionable URLs directly from the snapshot JSON.
|
| 40 |
+
"""
|
| 41 |
lines: List[str] = []
|
| 42 |
|
| 43 |
# --- Basic info ---
|
|
|
|
| 45 |
if title:
|
| 46 |
lines.append(f"TITLE: {_clean(title)}")
|
| 47 |
|
| 48 |
+
# --- FULL URL: Always provide complete https:// URLs, never relative paths ---
|
| 49 |
url = grant.get("url") or grant.get("link")
|
| 50 |
if url:
|
| 51 |
+
lines.append(f"URL: {url}") # Example: "https://apply-for-innovation-funding.service.gov.uk/competition/2276/overview/..."
|
| 52 |
+
|
| 53 |
+
# --- Funding information ---
|
| 54 |
+
funding = grant.get("funding") or {}
|
| 55 |
+
if isinstance(funding, dict):
|
| 56 |
+
max_funding = funding.get("max")
|
| 57 |
+
if max_funding:
|
| 58 |
+
lines.append(f"FUNDING: Up to £{max_funding:,}")
|
| 59 |
+
min_funding = funding.get("min")
|
| 60 |
+
if min_funding and min_funding != max_funding:
|
| 61 |
+
lines.append(f"MINIMUM FUNDING: £{min_funding:,}")
|
| 62 |
+
else:
|
| 63 |
+
funding_text = grant.get("funding_amount") or grant.get("amount") or grant.get("funding_rate")
|
| 64 |
+
if funding_text:
|
| 65 |
+
lines.append(f"FUNDING: {_clean(funding_text)}")
|
| 66 |
|
| 67 |
+
# --- Dates ---
|
| 68 |
+
deadline = grant.get("close_date") or grant.get("deadline")
|
| 69 |
if deadline:
|
| 70 |
lines.append(f"DEADLINE: {_clean(deadline)}")
|
| 71 |
|
| 72 |
+
open_date = grant.get("open_date")
|
| 73 |
+
if open_date:
|
| 74 |
+
lines.append(f"OPENS: {_clean(open_date)}")
|
| 75 |
+
|
| 76 |
+
# --- Core text sections from snapshot ---
|
| 77 |
sections = grant.get("sections") or {}
|
| 78 |
if sections:
|
| 79 |
+
# Process snapshot sections in order: summary, eligibility, scope, dates, how_to_apply
|
| 80 |
+
section_order = [
|
| 81 |
+
"summary_raw", "eligibility_raw", "scope_raw",
|
| 82 |
+
"dates_raw", "how_to_apply_raw", "supporting_information_raw"
|
| 83 |
+
]
|
| 84 |
+
for section_key in section_order:
|
| 85 |
+
v = sections.get(section_key)
|
| 86 |
+
if v and _clean(v): # Only include non-empty sections
|
| 87 |
+
section_name = section_key.replace("_raw", "").replace("_", " ").upper()
|
| 88 |
+
lines.append(f"\n{section_name}:\n{_clean(v)}")
|
| 89 |
else:
|
| 90 |
+
# Fallback to common text fields
|
| 91 |
desc = grant.get("description") or grant.get("summary") or grant.get("scope")
|
| 92 |
if desc:
|
| 93 |
+
lines.append(f"\nDESCRIPTION:\n{_clean(desc)}")
|
| 94 |
|
| 95 |
# --- Optional extras ---
|
| 96 |
eligibility = grant.get("eligibility")
|
| 97 |
if eligibility:
|
| 98 |
+
lines.append(f"\nELIGIBILITY:\n{_clean(eligibility)}")
|
| 99 |
|
| 100 |
scope = grant.get("scope")
|
| 101 |
if scope:
|
| 102 |
+
lines.append(f"\nSCOPE:\n{_clean(scope)}")
|
| 103 |
+
|
| 104 |
+
# --- Contact Information ---
|
| 105 |
+
lines.append("\n--- CONTACT INFORMATION ---")
|
| 106 |
+
lines.append("Email: support@iuk.ukri.org")
|
| 107 |
+
lines.append("Phone: 0300 321 4357")
|
| 108 |
+
lines.append("Hours: 9am-12pm, 2pm-5pm, Monday-Friday (excluding bank holidays)")
|
| 109 |
|
| 110 |
# --- Past winners summary ---
|
| 111 |
if past_winners:
|