偶然在 GitHub 上刷到一個專案,看了一下發現有點意思。這是一個 CLI 工具,你給它一個自然語言的問題,它會自己規劃步驟、調用工具、查數據,最後給你一個答案。就像有個金融分析師助理在幫你幹活。
先看看效果

你不需要告訴它該查什麼接口,不需要寫代碼,直接用自然語言問就行了。
整體架構
先看整體架構,不算複雜,但設計得挺乾淨:

核心思路就是:讓 LLM 來決定下一步該做什麼,而不是硬編碼一個流程。
代理循環:讓它自己思考
最有趣的是這個代理循環的設計。它不是一次性把活幹完,而是一步步來:

為什麼要這樣設計?
因為有些問題不是一步能搞定的。比如你問「分析一下蘋果的投資價值」,它可能需要:
先查財務數據 看完數據後發現還需要查一下行業對比 發現還缺少最新的新聞 最後綜合所有信息給出結論
如果一次性把所有可能的工具都調用一遍,既浪費錢又不一定有用。讓它自己判斷下一步需要什麼,會更靈活。
關鍵代碼邏輯:
// 簡化的代理循環while (iteration < maxIterations) {// 1. 調用 LLM 做決策const response = await callModel(currentPrompt);// 2. 沒有 tool_calls?說明準備生成答案了if (!hasToolCalls(response)) {return generateFinalAnswer(scratchpad.getFullContext());}// 3. 有 tool_calls?執行工具並收集結果for (const toolCall of response.tool_calls) {const result = await executeTool(toolCall);scratchpad.addResult(result); // 記錄到筆記本}// 4. 上下文太長?清理舊的結果if (estimateTokens(context) > THRESHOLD) {scratchpad.clearOldestResults(KEEP_COUNT);}// 5. 構建下一次迭代的提示currentPrompt = buildIterationPrompt(scratchpad.getResults());}
Scratchpad:它的「筆記本」
每次查詢,Dexter 都會創建一個 Scratchpad,就像給 AI 配了一個筆記本。這個筆記本記錄了:
一開始問了什麼問題 調用了哪些工具 每個工具返回了什麼結果 AI 中間有過哪些思考

持久化格式:每個查詢生成一個 JSONL 文件,每行一條記錄:
{"type":"init","content":"蘋果和特斯拉哪個更值得投資?","timestamp":"2026-02-08T..."}{"type":"tool_result","toolName":"financial_search","args":{"query":"AAPL TSLA 財務數據"},"result":{...},"timestamp":"..."}{"type":"thinking","content":"讓我對比一下兩家公司的估值指標...","timestamp":"..."}
三大能力:
防重試:通過 Jaccard 相似度檢測,不會重複查一樣的東西 控成本:當上下文太長時,自動清理舊結果 可追溯:每次查詢都有完整記錄,出問題能查日誌
去重邏輯:
// 檢測相似查詢findSimilarQuery(newQuery, previousQueries) {const newWords = tokenize(newQuery); // 分詞for (const prev of previousQueries) {const similarity = jaccard(newWords, tokenize(prev));if (similarity >= 0.7) return prev; // 相似度閾值}return null;}
工具系統:三層架構
工具系統分了三層,每層職責清晰:

為什麼需要路由層?
因為用戶的提問是自然語言,不是結構化的 API 調用。比如你說「看看蘋果最近表現如何」,它需要理解:
「表現」可能指股價,也可能指財務 「最近」是多長時間? 需要調用哪些具體的 API?
路由層用另一個 LLM 來做這件事,把自然語言翻譯成具體的工具調用:
// 路由層工作流程func: async (input) => {// 1. 用 LLM 理解用戶意圖const { response } = await callLlm(input.query, {tools: ALL_FINANCE_TOOLS, // 綁定所有金融工具});// 2. 提取工具調用const toolCalls = response.tool_calls;// 3. 並行執行(多個工具可以同時跑)const results = await Promise.all(toolCalls.map(tc => FINANCE_TOOL_MAP.get(tc.name).invoke(tc.args)));// 4. 合併結果return combineResults(results);}
金融工具詳解
Dexter 最大的價值在於它集成了豐富的金融數據工具。這些工具都是對 Financial Datasets API 的封裝,讓 AI 能夠像分析師一樣查數據。
工具全景圖

價格數據工具
get_price_snapshot - 獲取最新價格
// 調用示例get_price_snapshot({ ticker: "AAPL" })// 返回數據{"price": 178.52,"change": 2.35,"change_percent": 1.33,"volume": 52340000,"open": 176.80,"high": 179.12,"low": 176.20}
get_prices - 歷史價格數據
// 調用示例get_prices({ticker: "AAPL",start_date: "2024-01-01",end_date: "2024-01-31",interval: "day"})// 返回數據[{ "date": "2024-01-02", "open": 182.5, "high": 185.0, "low": 181.2, "close": 184.3, "volume": 52000000 },{ "date": "2024-01-03", "open": 184.0, "high": 186.1, "low": 183.5, "close": 185.9, "volume": 48000000 },// ...]
財務報表工具
get_income_statements - 利潤表
// 調用示例get_income_statements({ticker: "AAPL",period: "annual", // annual / quarterly / ttmlimit: 5})// 返回數據(5年年度利潤表)[{"fiscal_date": "2023-09-30","revenue": 383285000000,"cost_of_revenue": 214137000000,"gross_profit": 169148000000,"operating_income": 114301000000,"net_income": 96995000000,// ...},// ... 歷史數據]
get_balance_sheets - 資產負債表 get_cash_flow_statements - 現金流量表 get_all_financial_statements - 一次性獲取三張報表(效率更高)
估值指標工具
get_key_ratios_snapshot - 最新估值指標
// 調用示例get_key_ratios_snapshot({ ticker: "AAPL" })// 返回數據{"market_cap": 2800000000000,"pe_ratio": 28.5,"pb_ratio": 45.2,"dividend_yield": 0.5,"eps": 6.16,"revenue_per_share": 24.5,"enterprise_value": 2750000000000}
get_key_ratios - 歷史估值指標(用於趨勢分析)
SEC 文件工具
get_filings - 獲取 SEC 文件元數據
// 調用示例get_filings({ticker: "AAPL",filing_type: "10-K", // 10-K / 10-Q / 8-Klimit: 5})// 返回數據[{"accession_number": "0000320193-23-000108","filing_type": "10-K","filing_date": "2023-11-03","report_date": "2023-09-30","url": "https://www.sec.gov/..."},// ...]
get_10K_filing_items - 讀取 10-K 的具體章節
// 調用示例get_10K_filing_items({ticker: "AAPL",accession_number: "0000320193-23-000108",items: ["Item-1", "Item-1A", "Item-7"]// Item-1: Business// Item-1A: Risk Factors// Item-7: MD&A})// 返回數據{"Item-1": "Apple Inc. designs, manufactures...","Item-1A": "The Company's business is subject to...","Item-7": "Results of Operations..."}
get_10Q_filing_items - 季報章節 get_8K_filing_items - 重大事件公告
其他工具
get_news - 公司新聞 get_insider_trades - 內部交易(高管買賣記錄) get_analyst_estimates - 分析師預期和目標價 get_segmented_revenues - 分業務收入
如何使用 Dexter
安裝
# 1. 克隆專案git clone https://github.com/virattt/dexter.gitcd dexter# 2. 安裝依賴(需要 Bun)bun install# 3. 配置環境變量cp env.example .env# 編輯 .env,填入 API 密鑰
運行
# 啟動交互模式bun start# 開發模式(自動重載)bun dev
支持的模型
Dexter 支持多個 LLM 提供商,通過模型名稱前綴自動識別:
claude- | ||
gemini- | ||
grok- | ||
ollama: | ||
使用示例
# 啟動後,直接輸入問題> 蘋果最新的財報怎麼樣?> 對比一下特斯拉和比亞迪的估值> 分析英偉達的投資價值,用 DCF 方法> 查一下最近有哪些科技公司在回購股票
技能系統
Dexter 支持自定義技能,比如內置的 DCF 估值技能:
---name: dcf-valuationdescription: DCF 估值分析---## DCF Valuation Skill### Workflow Checklist- [ ] Step 1: Gather financial data- [ ] Step 2: Calculate FCF growth rate- [ ] Step 3: Estimate WACC- [ ] Step 4: Project future cash flows- [ ] Step 5: Calculate present value...
你可以添加自己的技能到 ~/.dexter/skills/ 目錄,Dexter 會自動發現並加載。
技能系統:把專家知識寫成文檔
這個設計我覺得最巧妙。有些複雜任務(比如 DCF 估值)有一套固定流程,如果把流程硬編碼進代碼裡會很死板。
Dexter 的做法是:把流程寫成 Markdown 文件,LLM 可以直接讀懂並執行。

效果:你想加一個新的分析模型,只需要寫個 Markdown 文件,不需要改代碼。
技能目錄結構:
~/.dexter/skills/├── dcf-valuation/│ └── SKILL.md├── pe-analysis/│ └── SKILL.md└── your-skill/└── SKILL.md
CLI 界面:用 React 寫終端
這個也挺有意思的。它用的是 Ink(React for CLI),不是傳統的 chalk/ora。

事件驅動的狀態管理:
// Hook 訂閱代理事件const handleEvent = (event) => {switch (event.type) {case 'thinking':setWorkingState({ status: 'thinking' });break;case 'tool_start':setWorkingState({ status: 'tool', toolName: event.tool });break;case 'tool_progress':updateProgress(event.message); // 實時更新進度break;case 'done':setAnswer(event.answer);break;}};// 代理流式輸出事件forawait (constevent of agent.run(query)) {handleEvent(event);}
好處:
組件化組織 UI,代碼清晰 事件驅動,代理不關心 UI 怎麼渲染 實時顯示進度,體驗更好
多模型支持與成本優化
Dexer 支持多個 LLM 提供商,還做了一些成本優化。
支持的提供商
// 通過前綴自動選擇提供商const MODEL_PROVIDERS = {'claude-': ChatAnthropic,'gemini-': ChatGoogleGenerativeAI,'grok-': ChatOpenAI, // xAI API'openrouter:': ChatOpenAI, // OpenRouter'ollama:': ChatOllama,};
Anthropic 提示詞緩存
// 啟用系統提示詞緩存function buildAnthropicMessages(systemPrompt, userPrompt) {return [new SystemMessage({content: [{type: 'text',text: systemPrompt,cache_control: { type: 'ephemeral' } // 關鍵!}]}),new HumanMessage(userPrompt)];}
效果:系統提示詞緩存後,輸入成本降低約 90%。
快速模型分流
const FAST_MODELS = {openai: 'gpt-4o-mini',anthropic: 'claude-haiku-4-5',google: 'gemini-2.5-flash',};
輕量級任務(如摘要)自動使用快速模型,節省成本。
能用在哪?
這個專案雖然是做金融的,但它的架構模式其實挺通用的:

實用價值:
對於想學習 AI Agent 開發的開發者,這個專案是一個很好的參考。代碼質量不錯,結構清晰,容易改。而且它的金融工具封裝也可以直接用在其他項目裡。
如果你想自己動手改改看,可以:
換成其他數據源(比如你自己爬的數據) 加一些自定義技能(比如技術分析指標) 換成 Web UI(Ink 可以換成 React) 做成不同的領域(醫療、法律、電商)
專案地址:https://github.com/virattt/dexter
技術棧:Bun + TypeScript + LangChain + Ink + Financial Datasets API
所需 API:
OpenAI API(或其他 LLM) Financial Datasets API(金融數據) Exa API(可選,網絡搜索)


