Deal Hunter scans RSS electronics feeds, estimates fair value for each deal with an ensemble, and pushes notifications when a discount clears a threshold.
The code you should treat as source of truth is in src/deal_hunter/. Notebooks in notebooks/ are for experiments.
- Config layer:
src/deal_hunter/config.pyusespydantic-settingsand loads.env. - Typed models:
src/deal_hunter/models/deals.pydefinesScrapedDeal,Deal,DealSelection, andOpportunity. - RSS ingestion:
src/deal_hunter/services/rss.pyparses feeds, fetches deal pages, and normalizes content. - Pricing stack:
src/deal_hunter/services/preprocessing.pyrewrites product text with LiteLLM.src/deal_hunter/agents/frontier.pydoes Chroma-based retrieval plus LLM price estimation.src/deal_hunter/agents/specialist.pycalls a Modal-hosted fine-tuned model.src/deal_hunter/agents/ensemble.pycombines frontier + specialist predictions with configured weights.
- Orchestration:
src/deal_hunter/agents/scanner.pyextracts top deal candidates using structured output.src/deal_hunter/agents/planner.pyscores deals and triggers notifications above threshold.src/deal_hunter/framework.pymanages memory (memory.json), Chroma collection, and end to end runs.src/deal_hunter/agents/autonomous_planner.pyincludes a tool-calling autonomous planner variant.
- Notifications:
src/deal_hunter/services/notifications.pysends Pushover messages. - UI:
src/deal_hunter/ui/app.pyprovides a Gradio dashboard with periodic runs and live logs. - Evaluation helper:
src/deal_hunter/services/testing.pyincludesTesterandevaluate(...).
flowchart TD
rss["RSS feeds"] --> scanner["ScannerAgent"]
scanner --> planner["PlanningAgent"]
planner --> ensemble["EnsembleAgent"]
ensemble --> preprocessor["Preprocessor"]
ensemble --> frontier["FrontierAgent + Chroma"]
ensemble --> specialist["SpecialistAgent - Modal Pricer"]
planner --> notifier["MessagingAgent to PushoverNotifier"]
framework["DealAgentFramework"] --> planner
framework --> memory["memory.json"]
framework --> chroma[(Chroma collection)]
ui["Gradio App"] --> framework
src/deal_hunter/agents/agent implementations and orchestration logic.src/deal_hunter/services/integration services (RSS, notifications, preprocessing, Modal pricer, testing).src/deal_hunter/models/pydantic domain models for deals and opportunities.src/deal_hunter/ui/Gradio app and log formatting.notebooks/scratch work and experiments.error_docs/errors.mdpractical notes for build/runtime issues.
- Python 3.11+ (the project currently uses 3.12)
uv- API/auth setup for:
- OpenAI-compatible provider (
OPENAI_API_KEY) - Hugging Face (
HF_TOKEN) for model/dataset access - Modal auth for specialist pricing
- Pushover credentials if you want push alerts
- OpenAI-compatible provider (
uv syncAt minimum:
OPENAI_API_KEY=your_key
HF_TOKEN=your_hf_tokenCommon extras:
GROQ_API_KEY=your_groq_key
OPEN_ROUTER_API_KEY=your_openrouter_key
PUSHOVER_USER=your_pushover_user
PUSHOVER_TOKEN=your_pushover_tokenuv run python -m deal_hunter.ui.appuv run python -m deal_hunter.frameworkuv run modal deploy src/deal_hunter/services/pricer.pypyproject.tomldeclaresdeal-hunter = deal_hunter.main:main, butsrc/deal_hunter/main.pydoes not exist yet.src/deal_hunter/nn/is currently a placeholder package.- There is a second ensemble/orchestration path in
src/deal_hunter/agents/autonomous_planner.py; the default path used by the UI goes throughDealAgentFramework+PlanningAgent.
- Experiment in
notebooks/. - Move stable code into
src/deal_hunter/. - Keep runtime settings in
src/deal_hunter/config.pyand.env. - Check
error_docs/errors.mdwhen troubleshooting Modal, memory, or retrieval issues.