Argus: a Java RAG knowledge base with hybrid retrieval and a ReactAgent dialogue layer
🌱 Argus 是一个基于 RAG 架构的开源知识库平台,后端采用 Java 21 + Spring Boot + MyBatis-Plus + PostgreSQL/pgvector,前端采用 Vue 3 + TypeScript + Element Plus,AI 层基于 Spring AI Alibaba(通义千问)+ ReactAgent 图引擎,以 MinIO + Elasticsearch 为存储与检索引擎。
At a glance
- What is it?
- Argus is a self-hosted RAG platform built on Spring Boot, pgvector and Elasticsearch, with a Vue 3 front end. It is aimed at teams that want citation-backed answers over private documents and are willing to run Postgres, Elasticsearch and MinIO themselves.
- Who is it for?
- Argus fits teams already running Java and Postgres who need citation-backed answers over private documents and can operate Elasticsearch and MinIO alongside them. It does not fit anyone wanting a single-binary or managed-hosted knowledge base, or teams unwilling to depend on Alibaba Cloud DashScope for both chat and embeddings.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 30 days ago.
- What is it written in?
- Mainly Java, 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 problem Argus targets: private documents that a general model cannot answer from
A general chat model has no access to an organisation's internal documents, and when asked about them it produces plausible text with no source. Argus is a self-hosted platform that indexes those documents and answers questions with citations back to the source fragments. The README frames the target as three failures: fabricated answers, knowledge scattered across files, and conversations with no memory of earlier turns. The intended user is a team that already has private documents (PDF, DOCX, Markdown, plain text) and wants a retrieval layer it controls, rather than a hosted assistant. Everything is deployed by the operator: PostgreSQL with pgvector, Elasticsearch, MinIO, and the Java and Vue applications. The model calls go out to Alibaba Cloud DashScope for both chat (Tongyi Qianwen) and embeddings (text-embedding-v3), so this is self-hosted retrieval with a hosted model. That split is the central design decision, and it shapes both the deployment cost and the data boundary.
Two retrieval channels and an RRF merge, not a single vector index
The retrieval path in the README runs two channels in parallel. Vector search uses pgvector with an HNSW index and COSINE_DISTANCE for semantic similarity. Keyword search uses Elasticsearch 8.x with the IK Chinese tokenizer and BM25 for exact term matching. Results from both are merged with Reciprocal Rank Fusion into one ranking, then expanded: the README describes cluster aggregation and neighbour window expansion to pull surrounding context so retrieved fragments are not isolated sentences. Before retrieval, an LLM performs query planning and picks one of three strategies: DIRECT, REWRITE or DECOMPOSE, with at most three parallel retrieval queries. After retrieval, a four-level evidence assessment (NONE, WEAK, PARTIAL, SUFFICIENT) decides whether the system answers at all; the README states that insufficient evidence triggers a refusal rather than a generated answer. This is the part of the project worth examining most closely. Two indexes mean two systems to keep in sync, and the ETL pipeline writes to both, so a partial failure in one leaves the corpus inconsistent. The README does not describe a reconciliation or reindex procedure, and that gap is the first thing an operator should look for in the code.
How a document becomes retrievable: Spring Event, @Async and @Retryable
Upload uses a three-phase chunked protocol: init, chunk upload, complete. The README states it supports resumable uploads and instant upload detection via SHA-256, so a file already stored is not transferred again. Chunks are written to MinIO, an S3-compatible object store that the README says is enabled conditionally through @ConditionalOnProperty, and merged with composeObject. Completion fires a Spring Event that triggers an asynchronous ETL pipeline, described as seven steps running under @Async with @Retryable and @Recover for declarative retries. Parsing covers PDF and DOCX through Apache PDFBox 2.0.31 and Apache POI 5.2.5, plus Markdown and plain text, with automatic encoding detection. The pipeline then cleans, chunks, embeds and indexes the content into pgvector and Elasticsearch. Because the trigger is an application event rather than a durable queue, an ETL job in flight when the process restarts is not obviously recoverable from the README alone. Retry semantics are declared, but where the retry state lives and whether a failed job can be replayed manually are not stated in the material, so treat that as something to confirm in the source before relying on it for a large backfill.
The agent layer: ReactAgent, mode switching and three levels of memory compression
The conversational side is built on Spring AI Alibaba's ReactAgent graph engine, which the README describes as a think, tool-call, respond loop. A session runs in one of two modes, CHAT or KB_SEARCH, and the mode can change within the same conversation. In KB_SEARCH the agent decides whether to call the retrieval tool, and the README notes it is limited to one retrieval call per turn to avoid wasted work. Responses stream to the browser over SSE, with delta deduplication and an AGENT_MODEL_FINISHED event as a fallback. Context is assembled before each model call through a BEFORE_MODEL hook that injects a compact summary, then session memory, then recent messages. Memory is compressed in three stages: an incremental LLM summary that keeps facts and decisions, a compacted historical summary that drops detail, and a runtime truncation applied when tokens exceed 50000. The truncation threshold is a fixed number in the README, not a value derived from the model's context window, so a deployment using a model with a smaller window would need to change it. The incremental summarisation also costs an extra model call per compression step, which is a recurring cost the README does not quantify.
Running it: the services and configuration keys the README names
The README lists the stack but the quick start section was truncated in the material supplied here, so the exact commands are not available to quote. What can be stated from the technology tables is the set of services a deployment must provide: PostgreSQL 16 or later with the pgvector extension, Elasticsearch 8.x with the IK analyser installed, MinIO, and a JDK 21 runtime for the Spring Boot 3.5 application, plus Node tooling for the Vue 3.5 front end built with Vite. Configuration keys explicitly named in the README are @ConditionalOnProperty for MinIO, meaning object storage can be switched off by property, and the JWT scheme, which uses HMAC-SHA256 with JJWT 0.12.6, a 15-minute access token and a refresh token stored in an httpOnly cookie with database-side rotation. The README also states the embedding vectors are 512 dimensions, which fixes the pgvector column width. API documentation is served through Knife4j and SpringDoc at /doc.html. Because the quick start was truncated, verify the required environment variables for DashScope credentials and the database connection directly in the repository before planning a deployment; do not assume the list above is complete.
Where Argus is the wrong choice
The operational footprint is the main constraint. A working installation needs PostgreSQL with an extension, Elasticsearch, MinIO and the JVM application. Elasticsearch alone is a substantial service to run, size and back up, and the README does not describe a way to run Argus without it, so a team wanting a single container or an embedded index will not find that here. The model dependency is the second constraint. Chat and embeddings both go to DashScope, and there is no described adapter for other providers in the material, so an organisation that cannot send document content to Alibaba Cloud cannot use the retrieval path as documented. The third is maturity signals rather than code quality: the repository has no releases, the README badge says MIT while the licence field in the repository metadata is unknown, and the quick start is thin enough to be truncated in the extract. None of that means the code is wrong, but it means the operator is reading source rather than documentation for anything beyond the happy path. Teams that need a vendor-supported platform with a support contract should look elsewhere.
The alternative to weigh: a Python RAG framework such as Haystack or LlamaIndex
The closest comparison is not another Java project but a Python RAG framework. Haystack and LlamaIndex both let you assemble a retrieval pipeline in Python, and both are libraries rather than applications: you write the indexing and query code, choose your vector store, and build your own API and front end. Argus takes the opposite approach. It ships the whole product, including user registration, JWT authentication, group collaboration with three roles and an approval flow for joining, chunked upload, an asynchronous ETL pipeline, an SSE chat interface, and an admin surface through Knife4j. The practical difference is where the work lands. With a framework you spend time on pipeline design and integration and get exactly the retrieval behaviour you specify; with Argus you spend time on deployment and on reading the source when the documented behaviour is not enough, and you inherit its choices, including the fixed 512-dimension embeddings, the one-retrieval-call-per-turn agent limit, and the 50000-token truncation threshold. If the retrieval strategy in the README matches what you need, adopting Argus skips months of plumbing. If you need a retrieval shape it does not implement, a framework is the shorter path.
Licence, maintenance and what to check before committing
The licence situation needs resolving first. The README displays an MIT badge, but the repository metadata supplied here records the licence as unknown and there are no releases. Those two signals conflict, and the difference matters: MIT permits commercial use and modification with attribution, while an unlicensed repository grants no rights by default. Confirm the actual LICENSE file at the repository root before building anything on top of Argus. Maintenance cost is dominated by the infrastructure rather than the application. Postgres, Elasticsearch and MinIO each need backup, upgrade and monitoring procedures, and the ETL pipeline writes to two indexes, so a restore that covers only one leaves the corpus inconsistent. Dependency upgrades are another recurring item: the stack pins Java 21, Spring Boot 3.5, Spring AI Alibaba 1.1.2.0, Elasticsearch 8.x and pgvector, and the Spring AI Alibaba line is young enough that version drift is likely. The 512-dimension embedding size is effectively a schema commitment; changing the embedding model later means re-embedding the corpus and rebuilding the HNSW index. That reindex path is the single most important thing to verify in the code before loading production documents, because the README does not describe one.
Editorial conclusion
Argus fits teams already running Java and Postgres who need citation-backed answers over private documents and can operate Elasticsearch and MinIO alongside them. It does not fit anyone wanting a single-binary or managed-hosted knowledge base, or teams unwilling to depend on Alibaba Cloud DashScope for both chat and embeddings. Before adopting it, verify three things in the repository: the actual licence file, whether the README's quick start lists every required service and environment variable, and whether the embedding dimension configured in your deployment matches the 512 dimensions the README states, since a mismatch invalidates the pgvector column.
Community notes