A plan-driven chatbot that converts natural-language queries into multi-step tool workflows and answers in Hebrew or English using a hybrid local-first + cloud-fallback LLM architecture.
ToolWeaver is designed to go beyond a single prompt/response chatbot. Instead of directly calling one model and hoping it handles everything, it:
- π§ generates a structured execution plan
- π resolves dependencies between tool calls
- βοΈ executes tools step by step
- π§© synthesizes one coherent final answer
- π grounds product answers through RAG over real documents
- π works end-to-end in both Hebrew and English
Most chatbot projects are thin wrappers around a single LLM call.
ToolWeaver explores a more structured approach: treat user queries as execution problems, not just prompts.
Instead of relying on one model to answer everything directly, the system separates the problem into stages:
- Planning β decide which tools are needed
- Execution β run those tools in dependency-aware order
- Synthesis β combine results into one final answer
This makes the system more:
- π§ interpretable β the reasoning path is explicit
- π§ extensible β new tools can be added without redesigning the app
- πΈ cost-aware β local models handle cheap/common tasks first
- π architecturally interesting β orchestration and ML workloads are clearly separated
- π§ Planner-driven orchestration β converts each message into a structured JSON tool plan
- π Dependency-aware execution β supports placeholders such as
<result_from_tool_1>between steps - π Bilingual flow β auto-detects Hebrew or English and responds in the same language
- π Document-grounded RAG β product queries are answered from indexed documents via ChromaDB retrieval
- π Local-first inference β Ollama handles general chat locally when possible
- βοΈ Cloud fallback β OpenAI handles planning, grounded generation, synthesis, and fallback reliability
- π§ͺ Review analysis pipeline β supports sentiment and aspect-level review analysis
- π§± Microservice split β Bun/TypeScript for orchestration, Python for ML/NLP workloads
User β POST /api/chat β Planner β JSON plan
β Executor β Toolβ β Toolβ β ... β ToolN
β Synthesis β Final response
| Layer | Stack |
|---|---|
| Frontend | React 19, Vite, Tailwind CSS |
| Backend | Bun, Express 5, TypeScript, Zod |
| AI / ML | Python (FastAPI), ChromaDB, sentence-transformers, DistilBERT |
| LLM | Ollama (local) + OpenAI (cloud) |
- Planner β converts user input into a JSON execution plan with 1β5 tool calls
- Executor β runs tools sequentially and resolves placeholders between steps
- Synthesis β merges multi-tool outputs into one coherent response
- RAG pipeline β retrieves product knowledge from local indexed documents
- Hybrid model router β uses Ollama first where possible and falls back to OpenAI when needed
This is not just a chatbot UI over an LLM API.
The project is interesting because it combines several engineering ideas in one system:
- π§ Explicit planning instead of implicit βsingle-shotβ reasoning
- π Multi-step tool chaining with inter-step dependency resolution
- π End-to-end bilingual behavior across planning, execution, and answer generation
- π βοΈ Hybrid local/cloud inference strategy to balance cost, latency, and quality
- π Grounded RAG answers for product information instead of free-form hallucinated responses
- π§± Service separation between orchestration logic and Python-based ML workloads
| Tool | Purpose | Source / Notes |
|---|---|---|
getWeather |
Weather lookup | Open-Meteo API |
getExchangeRate |
Currency rate lookup | Hardcoded rates |
calculateMath |
Safe math evaluation | Parser-based, no eval |
analyzeReview |
Review analysis / ABSA | OpenAI-based analysis |
getProductInformation |
Product Q&A over docs | Python retrieval + OpenAI RAG |
generalChat |
Free-form chat | Ollama primary β OpenAI fallback |
ΧΧ ΧΧΧ ΧΧΧΧΧΧ¨ ΧΧΧΧ ΧΧΧ ΧΧΧ Χ©Χ’Χ¨ GBP Χ-ILS?Tell me about the Smart Watch S5.Χ ΧͺΧ ΧΧ ΧΧͺ ΧΧΧΧ§ΧΧ¨Χͺ ΧΧΧΧͺ ΧΧͺΧΧΧ ΧΧ‘Χ€Χ§ΧΧΧ ΧΧΧΧΧΧΧ ΧΧ©ΧΧΧΧΧΧWhat is 15% of 240, and should I take a coat to Paris tomorrow?
For a user query like:
What's the weather in London and the GBP to ILS rate?
The system may execute a flow like this:
- π§ The planner receives the prompt and generates a JSON execution plan
- βοΈ The executor calls
getWeather - βοΈ The executor calls
getExchangeRate - π§© The synthesis layer combines both results into one final answer
- π The answer is returned in the userβs language
For more complex workflows, later steps can reference previous tool outputs using placeholders such as:
<result_from_tool_1>
That allows the executor to pass structured results from one step into the next.
- β JSON plan validation using Zod
- π Cascading fallback strategy: Ollama β OpenAI
- π Placeholder-based dependency resolution between tools
- π Local vector retrieval using ChromaDB +
sentence-transformers - π§± Clean split between TypeScript orchestration and Python ML services
- π Language-aware behavior for both Hebrew and English
- π‘ Safe math execution via parser rather than
eval
The executor currently runs tool calls sequentially. This keeps dependency handling simple and predictable, but increases total latency for multi-step workflows.
Ollama reduces cost and supports local-first execution, but it is less reliable for structured JSON generation. That is why planning and general chat include OpenAI fallback behavior.
Separating ML/NLP logic into Python makes model integration cleaner, but adds inter-service communication overhead and a larger failure surface.
ChromaDB is convenient for local development and demos, but a production system would likely need a managed vector database.
The full benchmark and architectural analysis are better treated as supporting documentation rather than the core README.
- β‘ Fastest component: local RAG retrieval
- π’ Slowest component: planner / routing stage
- πΈ Cheapest path: Ollama-only general chat
- π― Most accurate path: OpenAI-based RAG generation and synthesis
- π Best local wins: retrieval and basic sentiment tasks
- βοΈ Best cloud use cases: planning reliability, grounded generation, and final synthesis
Detailed latency, cost, and architecture analysis can live in a separate document such as:
docs/benchmarking-and-analysis.md
ToolWeaver is designed with practical fallback behavior rather than assuming every component always succeeds.
- If Ollama fails, planning/chat can fall back to OpenAI
- If the Python service is unavailable, chat/weather/math may still work
- If synthesis fails, raw tool results can still be concatenated
- If a specific tool fails mid-plan, the system degrades rather than fully crashing when possible
This is not full production-grade resilience yet, but it demonstrates deliberate fault-aware design.
| # | Improvement | Why it matters |
|---|---|---|
| 1 | Caching | Reduce repeated planner and RAG costs |
| 2 | Parallel execution | Run independent tools concurrently |
| 3 | Smart routing | Skip planner for obvious single-tool queries |
| 4 | Planner fine-tuning | Improve local planner reliability |
| 5 | Circuit breaker + retry | Improve Python service reliability |
| 6 | gRPC | Reduce TypeScript β Python overhead |
| 7 | Managed vector DB | Improve persistence and scalability |
| 8 | Redis conversation store | Replace history.json for safer state handling |
| 9 | Similarity thresholding | Improve retrieval precision |
| 10 | Query expansion | Improve recall for KB search |
- Bun
- Python 3.10β3.12 with
pip - OpenAI API key
- Ollama (optional but recommended)
To use Ollama locally:
ollama pull llama3.2bun installCreate apps/server/.env:
OPENAI_API_KEY=sk-your-key-here
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=llama3.2
PY_SERVICE_URL=http://localhost:8000
DEFAULT_LOCALE=auto
PORT=3000cd services/python
py -3.12 -m venv .venvWindows
.venv\Scripts\activatemacOS / Linux
source .venv/bin/activateThen install dependencies:
pip install -r requirements.txtcd services/python
python index_kb.py --rebuildTerminal 1 β Python microservice
cd services/python
.venv\Scripts\activate # Windows
uvicorn server:app --host 0.0.0.0 --port 8000Terminal 2 β backend + frontend
bun run devClient runs on:
http://localhost:5173
Request:
{ "prompt": "What's the weather in London and the GBP to ILS rate?", "conversationId": "uuid-v4" }Response:
{ "message": "London: 12Β°C, Partly cloudy. The GBP to ILS rate is 4.7000." }prompt: required, 1β1000 charactersconversationId: required, UUID v4- using
/resetas the prompt clears conversation history
| Endpoint | Method | Description |
|---|---|---|
/analyze |
POST | Sentiment / review analysis |
/search_kb |
POST | Semantic search over product docs |
/health |
GET | Health check |
apps/server/ TypeScript backend β orchestration, tools, LLM clients
apps/client/ React chat UI (Vite + Tailwind)
services/python/ Python microservice β sentiment analysis, KB search
data/products/ Product documents for RAG
docs/ Architecture, validation queries, verification guide
examples/sample_logs/ Multi-tool execution log examples
scripts/dev.ts Dev runner for server + client
| Problem | Fix |
|---|---|
| Ollama not available | Install Ollama or rely on OpenAI fallback |
| Ollama timeout | Increase timeout or use a smaller model |
| KB service initialization failed | Run python index_kb.py --rebuild |
| Product queries return empty | Make sure the Python service is running on port 8000 |
| Mixed-language output | Use a stronger multilingual model or rely on fallback |
bun run format
cd apps/server && bun run build
cd apps/client && bun run lintToolWeaver demonstrates more than a chat interface.
It shows how to build a planner-driven AI system with:
- π§ structured tool orchestration
- π dependency-aware multi-step execution
- π bilingual UX
- π βοΈ hybrid local/cloud model routing
- π grounded RAG over local documents
- π§± service separation across TypeScript and Python
- βοΈ explicit engineering tradeoffs around latency, cost, and reliability
ToolWeaver is a bilingual, plan-orchestrated chatbot that turns user queries into explicit tool workflows rather than single-shot model calls.
Its main value is not just answering questions, but demonstrating how planning, execution, fallback strategy, RAG grounding, and hybrid model routing can be combined into a more structured AI application architecture.