Skip to content

feat(cookbook): add crash-resilient LangGraph financial analyst - #95

Open
wangshen-tech wants to merge 1 commit into
sdageltc:mainfrom
wangshen-tech:feat/issue-82-financial-agent
Open

feat(cookbook): add crash-resilient LangGraph financial analyst#95
wangshen-tech wants to merge 1 commit into
sdageltc:mainfrom
wangshen-tech:feat/issue-82-financial-agent

Conversation

@wangshen-tech

Copy link
Copy Markdown

Description

Adds a real-world LangGraph financial analyst cookbook using yfinance, DeepSeek, and LetItLoop @durable_async checkpoints.

Closes #82

Architecture

The compiled async StateGraph runs four durable nodes:

START
  -> fetch_market_data
  -> compute_indicators
  -> generate_investment_memo
  -> generate_report
  -> END

Every node executes through await async_step(...), so completed JSON-safe outputs are committed to LetItLoop's WAL before the graph advances.

Installation and usage

python -m pip install -e ".[financial-agent]"

# Deterministic and free
python examples/cookbooks/langgraph_financial_analyst.py --ticker AAPL --offline
python examples/cookbooks/langgraph_financial_analyst.py --ticker AAPL --offline --demo

# Live yfinance + DeepSeek
export DEEPSEEK_API_KEY="your-key"
python examples/cookbooks/langgraph_financial_analyst.py \
  --ticker AAPL \
  --model deepseek:deepseek-v4-flash \
  --live

API keys are read only from the environment and are never persisted in WAL or the independent call log.

SIGKILL recovery proof

On POSIX, the demo sends a real SIGKILL immediately after generate_investment_memo returns from its durable step. Windows uses exit 137 because it has no POSIX SIGKILL.

At the interruption point, WAL contains exactly:

  • fetch_market_data
  • compute_indicators
  • generate_investment_memo

generate_report is still absent. A separate fsynced JSONL receipt log audits successful market and LLM calls independently of WAL.

Observed live AAPL + DeepSeek demo:

Metric After SIGKILL After recovery Fully cached rerun
Market fetch calls 1 1 1
LLM calls 1 1 1
Provider-reported tokens 1059 1059 1059

This demonstrates zero re-fetching, zero duplicate LLM calls, and 0% duplicate token consumption for already committed steps. These are the live provider's actual usage fields; offline mode uses deterministic simulated accounting without making a paid request.

The guarantee is intentionally scoped to committed steps. If a process dies after an external provider receives a request but before that result is committed, exactly-once billing requires provider-side idempotency and is not claimed here.

<1ms measurement scope

The demo initializes and loads WAL first, then times only these in-memory calls:

await async_step("fetch_market_data", must_not_execute)
await async_step("compute_indicators", must_not_execute)
await async_step("generate_investment_memo", must_not_execute)

The fallback callback raises if any underlying function executes. Python startup, imports, WAL initialization, graph construction, and the unfinished report node are excluded.

Observed locally:

  • fetch_market_data: 0.006ms
  • compute_indicators: 0.002ms
  • generate_investment_memo: 0.001ms

CI uses a relaxed 25ms ceiling to avoid timing flakes while still strictly verifying that the callbacks are not executed.

Coverage

  • One year of yfinance history and JSON-safe fundamentals
  • SMA20, SMA50, Wilder RSI14, and MACD(12, 26, 9)
  • Real StateGraph.compile() + await graph.ainvoke(...)
  • DeepSeek via the repository's orchestrator.llm.call_llm
  • Offline injectable market and LLM fakes
  • Normal run and fully cached rerun
  • Real post-memo SIGKILL recovery
  • No repeated market fetch, LLM call, or token usage after recovery
  • Ticker-isolated WAL identities
  • Clear yfinance and LLM failure messages

Verification

pytest tests/test_cookbooks.py -q
13 passed

ruff check examples/cookbooks/langgraph_financial_analyst.py tests/test_cookbooks.py
All checks passed!

ruff format --check examples/cookbooks/langgraph_financial_analyst.py tests/test_cookbooks.py
2 files already formatted

pytest -m fast -q
518 passed, 4 skipped

pytest
1496 passed, 7 skipped

A live AAPL + DeepSeek post-memo SIGKILL demo completed successfully with exit code 0 and 1059 provider-reported tokens before and after recovery. No API key is included in this change.

@sdageltc sdageltc left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @wangshen-tech! Thank you so much for putting together this comprehensive LangGraph financial analyst cookbook using yfinance and DeepSeek! 🚀

The cookbook logic and test structure look great. However, this branch was created from an older base commit before our recent v0.5.2 Multi-Framework Adapter Suite release (letitloop/adapters/). As a result, merging directly would cause conflicts and remove existing adapter files.

Could you please rebase your branch against the latest origin/main?

git fetch origin
git checkout feat/issue-82-financial-agent
git rebase origin/main
# If any merge conflicts arise in README.md / CHANGELOG.md, resolve them keeping both the adapters and your new cookbook section
git push --force-with-lease

Once rebased, we will run the test matrix and merge immediately. Thank you for the awesome contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cookbook: Crash-Resilient Financial Analysis Agent with yfinance + LangGraph + @durable

2 participants