Create a .env file at the repository root:
OPENAI_API_KEY=...
FRED_API_KEY=...Install backend dependencies:
cd backend
poetry installIf you do not use Poetry, create a Python 3.12 virtualenv in backend/.venv and install the runtime dependencies there:
cd backend
uv venv --python 3.12 .venv
uv pip install --python .venv/bin/python \
openai==1.44.0 \
httpx==0.27.2 \
python-dotenv==1.0.1 \
langchain==0.2.16 \
pandas==2.2.3 \
matplotlib==3.9.2 \
requests==2.32.3Install frontend dependencies:
cd frontend
pnpm installStart the API first on port 8000, then:
cd frontend
pnpm run devIn development, Vite proxies /chat, /charts, and /health to http://127.0.0.1:8000. To point the UI at another backend:
VITE_CHAT_API_URL=http://localhost:8000/chat pnpm run devThe smoke tests use the real OpenAI and FRED keys to verify the LangChain/OpenAI planning path and one grounded answer:
cd backend
poetry run python -m unittest tests.test_openai_smokeOr, if you used the uv virtualenv:
cd backend
.venv/bin/python -m unittest tests.test_openai_smokeThey skip if OPENAI_API_KEY or FRED_API_KEY is missing.
Main class: submission.macro_specialist.MacroSpecialist
from submission.macro_specialist import MacroSpecialist
specialist = MacroSpecialist()
response = specialist.ask("Compare GDP growth rates between the US and the Eurozone over the last decade.")
print(response.answer)
print(response.sources)
print(response.chart_url)MacroSpecialist.ask(question: str) -> SpecialistResponse
The response contains:
answer: concise model-written answer grounded in retrieved observationsseries: selected series metadata from the data source clientssources: readable source labelschart_path/chart_url: generated PNG path and browser URL for plot/chart questions, otherwiseNone
Supporting classes: DataSourceClient, FredClient
search_series(query, limit=5)searches FRED series by text.observations(series_id, observation_start=None, observation_end=None, limit=120)returns a cleaned Pandas dataframe of dates and numeric values.
The implementation uses LangChain for prompt composition and runnable chains, but keeps the OpenAI call direct through the official OpenAI client because the provided dependency set includes langchain, not langchain-openai.