Model or dataset
iamzulx/crypto-rag avatar
iamzulx/crypto-rag

crypto-rag: an Indonesian-language crypto assistant that keeps prices out of the vector store

Asisten crypto berbahasa Indonesia: RAG pengetahuan 267 topik + data pasar realtime (6 bursa, WebSocket, derivatif, on-chain, TVL, DeFi) + tool-calling agent + LLM synthesis

738 stars7 forksPythonMIT

At a glance

What is it?
crypto-rag splits crypto questions into two paths: a FAISS knowledge corpus for concepts and live tool calls for numbers. The design decision is sound, the documentation is Indonesian-only, and the LLM layer is optional.
Who is it for?
Adopt crypto-rag if you need an Indonesian-language crypto Q&A tool and you are willing to read the README in Indonesian to configure it. Do not adopt it if you need a stable public API, non-Indonesian output, or a hosted service.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The stale-number problem crypto-rag is built around

Most retrieval-augmented generation systems for financial topics fail in a specific way: someone embeds a price into a vector store, the price changes, and the system keeps returning the old figure with full confidence. crypto-rag's README states the core principle directly: never put market numbers into the vector store, because they go stale instantly. Numeric data (price, funding, TVL) is fetched live at query time through a tool call; RAG is reserved for concepts, descriptions and static context. The README also claims numbers never pass through the LLM, which it presents as removing the risk of hallucinated prices. That second claim is the more interesting one, and it is only partly true depending on which flags you enable, since LLM synthesis is an explicit option. The audience is Indonesian-speaking users asking crypto questions: what is impermanent loss, what is the funding rate on BTC right now, how much TVL does Aave hold. The project is Python, MIT licensed, and has no homepage listed in the repository metadata.

Router, FAISS corpus and RRF: the retrieval path

The README includes an ASCII diagram of the query flow. A question enters a router that detects intent, then branches. Concept and education questions go to a knowledge corpus indexed in FAISS. Price questions go to six exchanges plus a WebSocket feed. Derivative and funding questions go to Binance Futures. TVL and on-chain questions go to DefiLlama. Sentiment questions go to the Fear and Greed Index. Market cap and category questions go to a static coin index that combines FAISS with Reciprocal Rank Fusion. All branches can optionally converge on an LLM synthesis step that produces a grounded answer with citations and a timestamp. Retrieval itself is hybrid: BM25 for keyword matching plus dense embeddings in FAISS, merged through RRF. A cross-encoder reranker is available behind the --rerank flag, which the README describes as more precise and slower. The knowledge corpus is described as 146 or more Indonesian topics spanning concepts, technology, categories, trading, risk, protocols, strategy, history, networks, security, metrics, ecosystems, regulation and more. A separate coin index carries 615 tagged coins filterable by category such as defi, meme, AI, stablecoin or layer-1.

Setup is three scripts and a pip line

The README gives an explicit setup sequence. Create a virtual environment, then install requests, numpy, faiss-cpu, fastembed and websocket-client. Then run fetch_data.py to pull coin data, index.py to build the embedding and FAISS index for coins, and knowledge_index.py to build the index for the knowledge corpus. An optional step, enrich_categories.py --pages 1, enriches coin categories from CoinGecko, and the README notes you must rerun index.py afterward to rebuild with the new categories. LLM configuration is optional and lives in config.json, copied from config.example.json, with three keys: OPENAI_BASE_URL, OPENAI_API_KEY and OPENAI_MODEL. The example values point at StepFun's endpoint with the model step-3.5-flash. The README states that environment variables of the same names are also supported and take precedence over config.json. Without any of this configuration the system runs in extractive mode, returning retrieved passages rather than generated prose. That fallback is a real design choice, not a footnote: it means the retrieval layer can be evaluated independently of any LLM.

What the CLI actually exposes

Running rag.py with no arguments enters interactive chat mode, which the README says keeps follow-up memory, so a question like "berapa harganya sekarang" resolves against the previously discussed coin. A positional string runs a single query. Flags change behaviour: --live adds sub-second WebSocket prices to realtime answers, --watch streams prices in the terminal, --stream prints LLM output token by token, --agent forces the tool-calling agent, --rerank enables the cross-encoder, --rule forces extractive answers with no LLM, and --k sets how many documents are retrieved (default 5). Watch mode accepts conditional alerts in the form BTC>65000 or ETH<1800, and multiple symbols can be mixed with alert expressions in one invocation. There is a portfolio tracker driven through natural-language strings: "portfolio tambah 0.5 BTC harga 60000" adds a holding with a cost basis, and a bare "portfolio" prints live value, P/L and allocation. A golden set of 87 queries is included for retrieval evaluation via eval_rag.py, which is a concrete way to check whether your index build produced sensible results before you trust any answer.

The optional LLM is where the grounding claim gets softer

The README's strongest architectural claim is that numbers never pass through the LLM and therefore price hallucination is impossible. The same README lists LLM synthesis as a feature that weaves knowledge and live data into a natural answer with citations and a disclaimer. Those two statements sit in tension. In extractive mode the claim holds cleanly: the system returns retrieved text and fetched values. Once synthesis is enabled, live values are placed into a prompt and the model writes prose around them, so the guarantee becomes a matter of prompt construction rather than architecture. The README does not document the prompt template or describe how the synthesis step is constrained to the supplied values, so a reader cannot verify from the repository description alone how tightly the model is held to the fetched numbers. The fallback to extractive answers when no LLM is configured is a sensible safety net, but it does not resolve the question of what happens when a model is configured and paraphrases a figure. That is the first thing to inspect in the source if accurate numbers matter to your use case.

Data dependency, language scope and the absence of releases

crypto-rag has no API keys for market data, which is a genuine convenience, but it also means every data path depends on third-party public endpoints: CoinGecko for coin data and category enrichment, Binance for spot, candles and futures, OKX, Bybit, KuCoin, Kraken and Coinbase for cross-exchange comparison, DefiLlama for TVL and stablecoin supply, Mempool.space for Bitcoin fees and mempool, and the Fear and Greed Index for sentiment. Any of these can rate-limit, change shape or go down, and the README does not describe retry, caching or degradation behaviour for those cases beyond the general note that fetch_data.py has a cache with a --fresh override. The second constraint is language: the corpus, the CLI examples and the README are Indonesian. If your users ask in English, the knowledge retrieval path is mismatched by design, and nothing in the material suggests an English corpus exists. The third is distribution. The repository metadata shows no releases retrieved and no homepage, so installation is from source on the master branch. There is no versioned artifact to pin, which makes upgrade cost hard to reason about: you track master and read the diff. The MIT licence is permissive and places few obligations on reuse, but this is a description of the licence text, not legal advice, and anyone embedding the project in a commercial product should read the licence themselves.

How this differs from a general-purpose agent framework

A tool-calling framework such as LangChain takes the opposite default: retrieval is one tool among many, and the model decides when to retrieve, when to call an API and when to answer from parametric memory. crypto-rag inverts that. The router decides the path before any model is involved, and the LLM is confined to synthesis at the end. The practical difference is predictability. A router-based design gives you a testable mapping from question shape to data source, which is why an 87-query golden set and an eval_rag.py script make sense here. An agent-based design gives you flexibility on questions the router never anticipated, at the cost of a model that might skip retrieval entirely. crypto-rag does have an agent mode behind --agent, described as routing complex multi-step queries to an LLM that picks its own tools, so the project is not purely deterministic. But the default path is the router, and the README's examples (funding rate BTC, TVL Aave, slippage beli BTC 5 juta) are all single-intent questions that the router handles without a model in the loop. If your queries are mostly of that shape, the router is the cheaper and more auditable choice. If they are not, you are paying for a system whose main design commitment does not match your workload.

Who should run this, and what to check first

crypto-rag fits a specific situation: you want an Indonesian-language crypto Q&A tool, you are comfortable running Python scripts and rebuilding FAISS indexes yourself, and you value the separation between static knowledge and live numbers enough to accept a source install with no release tags. It does not fit a team that needs a hosted API, an English corpus, or a pinned version with a changelog. The verification order is concrete. Run fetch_data.py first and confirm it completes, because index.py and every coin-category query depend on it. Then run knowledge_index.py and eval_rag.py against the 87-query golden set to see whether retrieval behaves before you add an LLM. Only after that configure config.json or the OPENAI_BASE_URL, OPENAI_API_KEY and OPENAI_MODEL environment variables, and compare a synthesized answer against the same query under --rule to see whether the model stayed inside the fetched values. If the two answers diverge on a price, the grounding claim in the README is weaker in practice than it reads on paper.

Editorial conclusion

Adopt crypto-rag if you need an Indonesian-language crypto Q&A tool and you are willing to read the README in Indonesian to configure it. Do not adopt it if you need a stable public API, non-Indonesian output, or a hosted service. Before running anything, verify that fetch_data.py and index.py complete against the current CoinGecko endpoints, since the whole retrieval path depends on those two scripts succeeding first.

Official sources

  1. iamzulx/crypto-rag on GitHub
  2. Issues
  3. License: MIT
  4. README
Community notes

Community notes