Repository navigation
Releases
Releases · sadrmanesh/persian-rag
v0.5.0
Changed
RewritingRetrievergives the query variants a fixed total weight. The original query keepsoriginal_weight(2.0), and the other variants split the newvariant_weight(1.0) evenly, instead of each getting 1.0. Before, a query with five spelling or spacing rewrites could let them outvote the original query, so the number of variants acted as a hidden ranking parameter. Fused scores, and in some cases the order of results, change for queries with two or more variants. Passvariant_weightto tune the family weight. The async path uses the same weights. Fixes #11.- The package version is now 0.5.0.
Added
metadata["query_contributions"]onRewritingRetrieverresults: the part of the fused score each matched variant added.RewritingRetriever.weights(count)returns the fusion weights used for a given number of queries.intfloat/multilingual-e5-baseas a supported, more accurate embedding model.SentenceTransformerEmbedder("e5-base"),--model e5-base, and the full model name all work, with the E5query:/passage:prefixes added automatically. e5-small stays the default.- Short model names:
e5-smallande5-baseresolve to the fullintfloat/multilingual-e5-*names wherever asentence-transformersmodel name is accepted (Python, CLI, saved index specs,run_benchmark.py). Indexes store the full name. E5_BASE_MODEL,ST_MODEL_ALIASES, andresolve_model_namein the public API.- e5-small against e5-base in the docs and README. nDCG@10, normalized text: MIRACL fa dev 0.7461 against 0.7657, PQuAD validation 0.9242 against 0.9247, persian-rag-bench 0.9881 against 1.0000. With perturbed queries (Arabic yeh and kaf, no half spaces, no normalization): MIRACL 0.6645 against 0.7089, PQuAD 0.8639 against 0.8906. e5-base is 278M parameters and 768 dimensions against 118M and 384, and encodes about 2.4 times slower on CPU.
Commits: 8cb56a6, ae45496. Full diff: v0.4.0...v0.5.0
v0.4.0
Changed
- Breaking default:
SentenceTransformerEmbedder()andpersian-rag ingest --embedder sentence-transformersnow useintfloat/multilingual-e5-smallinstead ofsentence-transformers/paraphrase-multilingual-MiniLM-L12-v2. Both have 118M parameters and 384 dimensions, but their vectors are not compatible. Code that names a model, and indexes built with any model, keep working, because indexes store their model. Rebuild indexes made with the old default to use the new model, or pass--model sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2to keep it. - The Docker image sets
HF_HOME=/data/.cache/huggingface, so models are cached in the/datavolume when the image is built with thesentence-transformersextra. benchmarks/run_benchmark.pydefaults to e5-small for--embedder sentence-transformersand has a--prefixoption.- The package version is now 0.4.0.
Added
- E5 query and passage prefixes.
SentenceTransformerEmbedder(prefix="auto")addsquery:andpassage:for E5 models (multilingual-e5-*,e5-*) andpersian-rag-embedmodels, and nothing for other models. When a model defines non-emptyqueryanddocumentprompts, those are used throughencode_queryandencode_document.prefix="e5"andprefix="none"force the choice, andquery_prefixandpassage_prefixset custom strings. persian-rag ingest --prefix auto|e5|none,--query-prefix, and--passage-prefix.- Indexes store the resolved prefixes, so a saved index is always queried the way it was built. Indexes from earlier versions have no stored prefixes and are queried without them; an E5 index from before 0.4.0 also gives a warning that suggests a rebuild.
- Model mismatch detection: loading an index with an embedder of a different kind or model raises
IndexFormatErrorwith a rebuild hint, and different prefixes give a warning. GET /healthreturns anembedderobject withkind,model,dimension,query_prefix, andpassage_prefix.DEFAULT_ST_MODEL,LEGACY_ST_MODEL,is_e5_model, andresolve_prefixesin the public API.- An optional Docker Hub job in the release workflow. When the
DOCKERHUB_USERNAMEandDOCKERHUB_TOKENsecrets are set, it copies the released GHCR image todocker.io/<username>/persian-ragwith the same tags. Without them it skips. - Links to the live demo on Hugging Face Spaces and the benchmark dataset on the Hugging Face Hub in the README and docs, with a Spaces badge.
.github/workflows/mirror.yml, which mirrorsmainand tags togitlab.com/sadrmanesh/persian-ragwhen theGITLAB_TOKENsecret is set, and skips cleanly otherwise.- Embedding model results in the docs and README. nDCG@10 on CPU with normalized text, MiniLM-L12-v2 against e5-small with prefixes:
- MIRACL fa dev (632 queries, pooled corpus of 6,405 judged passages, not the full MIRACL corpus, so not comparable with published MIRACL scores): 0.4424 against 0.7461 (MRR@10 0.4271 against 0.7138, Recall@10 0.6356 against 0.9521).
- PQuAD validation (5,995 questions, 1,103 paragraphs): 0.6437 against 0.9242 (MRR@10 0.5905 against 0.9042, Recall@10 0.8113 against 0.9845).
- persian-rag-bench, dense: 0.8637 against 0.9881. Without prefixes e5-small scores 0.9824, and 0.8333 instead of 0.9167 Hit@1 on the spelling subset.
Fixed
SentenceTransformerEmbedderno longer logs a deprecation warning on newer sentence-transformers versions, which renamedget_sentence_embedding_dimensiontoget_embedding_dimension.
v0.3.1
Added
- A production
Dockerfilefor the HTTP API. The image installspersian-rag[server,pdf,docx]on Python 3.12 from a wheel built in a separate stage, runs as a non-root user, serves/data/indexon port 8000, and has a health check onGET /health. TheEXTRASbuild argument adds other extras, such assentence-transformers. - A
.dockerignorethat keeps tests, docs, caches, and local indexes out of the build context. - The release workflow publishes the image to the GitHub Container Registry as
ghcr.io/sadrmanesh/persian-ragforlinux/amd64andlinux/arm64, taggedX.Y.Z,X.Y, andlatest, with OCI labels that link it to this repository. - CI builds the image, indexes a sample document inside it, checks
/healthand/retrieve, waits for the health check to report healthy, and checks that the container does not run as root. - A Docker page in English and Persian, and Docker sections in the README, the HTTP API page, and the release guide.
Changed
- The package version is now 0.3.1.
v0.3.0
Added
- Web loaders:
load_url,load_urls, andload_htmlwith readability-style main-content extraction (extract_main_content,html_to_text). Navigation, footers, comments, share bars, and hidden elements are removed,<article>and<main>are preferred, charsets are detected from headers and<meta>, and page title, language, description, author, and publish date go into metadata. Standard library only. - Markdown loading with front matter metadata, a title from the first heading, and optional splitting into one document per heading (
load_markdown(..., split_sections=True),split_markdown_sections).load_documentsreads.htmland.htmfiles and acceptssplit_sectionsandhtml_extract. ElasticsearchStoreandOpenSearchStore: vectors, text, and metadata in one index, k-NN for dense search and BM25 with thepersiananalyzer for sparse search, with add, upsert, delete, and API key or basic authentication. They talk to the REST API directly and need no client package.store_from_urlbuilds one from anelasticsearch://oropensearch+https://URL.HybridRetriever(sparse_backend=...)to run the BM25 half in a search engine, plusdelete_document,delete_chunks,document_ids, andchunk_ids_for_document.InMemoryVectorStoreand the in-process BM25 index support deletes.- Incremental indexing:
content_hash,IndexManifest, andIncrementalIndexerwithsync,upsert, anddelete. Unchanged documents are skipped and vectors of unchanged chunks are reused. Saved indexes store the manifest. - Persian query rewriting:
QueryRewriterwith spelling groups (اتاق/اطاق, تهران/طهران, هیئت/هیات, مسئله/مساله, and more), hamza and alef madda forms, affix spacing variants, optional Arabic letter variants, and optional LLM rewrites.RewritingRetrieverfuses the variant rankings with RRF and recordsmatched_queries. - Citation-grounded answers:
RAGPipeline(citations=True)numbers the contexts, andextract_citationsresolves[n]markers (Persian and Arabic-Indic digits included) to the best supporting sentence with document, chunk, and answer offsets.RAGAnswergainedcitations,uncited, andto_dict(). - Conversation memory:
ConversationMemoryandChatSessionwith LLM or heuristic condensing of follow-up questions, sync and async. - LLM adapters:
OpenAICompatibleLLM,OllamaLLM, andcreate_llm, with retries for timeouts, 408, 409, 429, and 5xx responses, and a pluggable transport. Standard library only. - HTTP API:
POST /chatandDELETE /chat/{session_id}, andcitationsanduncitedin/queryresponses. - CLI:
persian-rag chat;ingestaccepts several paths and URLs and gains--split-sections,--html-extract,--update, and--keep-missing; pipeline commands gain--llm ollama,--ollama-url,--llm-max-tokens,--citations, and--expand none|rules|llm. - Benchmark:
benchmarks/run_benchmark.pywith a 34-document Persian corpus and 42 labelled questions, comparing sparse, dense, and hybrid retrieval with and without query rewriting. Results are published in the documentation. - Documentation pages for web loaders, Elasticsearch and OpenSearch, incremental indexing, query rewriting, citations and chat, LLM adapters, and benchmarks, in English and Persian.
- CI job running integration tests against Elasticsearch 8 and OpenSearch 2.
Changed
persian-rag ingeststores a document manifest inindex.jsonand reports document and chunk counts. Indexes from 0.2.0 still load; the first--updatetreats every document as updated, reuses vectors of unchanged chunks, and writes the manifest.--llm openainow usesOpenAICompatibleLLM, so it retries transient errors.
v0.2.0
Added
- Rerankers: a
Rerankerprotocol,CrossEncoderReranker(rerankextra, default modelBAAI/bge-reranker-v2-m3), and a listwiseLLMRerankerthat tolerates loosely formatted replies. RAGPipeline(reranker=..., rerank_candidates=...)andRAGPipeline.retrieve(); reranked results keep the first-stage score inRetrievalResult.retrieval_score.- Vector stores in the new
persian_rag.vectorstorespackage:QdrantVectorStore(qdrantextra) andPgVectorStorefor PostgreSQL with pgvector (pgvectorextra), both with delete support. - PDF (
pdfextra) and Word (docxextra) loaders. PDF text is cleaned of presentation forms and bidi controls, and lines stored in visual order are detected and repaired.load_documentsnow reads.pdfand.docxfiles and can split PDFs by page. - Evaluation module: hit rate, MRR, recall, and nDCG at several cut-offs, document or chunk matching, JSONL datasets, and a faithfulness scorer protocol with token-overlap and LLM-judge implementations.
- FastAPI server (
serverextra) with/health,/retrieve, and/query, created throughpersian_rag.server.create_app. - Async support:
HybridRetriever.aretrieve,RAGPipeline.aretrieve, andRAGPipeline.aquery, which accepts async or sync model callables. - Caching:
CachedEmbedderwith in-memory and SQLite embedding caches, and an LRU/TTL result cache forHybridRetriever. - CLI:
persian-rag evalandpersian-rag serve, plus--rerank,--rtl-fix,--split-pages, and--embedding-cacheoptions. - Bilingual documentation site (English and Persian) built with MkDocs Material.
- Release workflow that publishes to PyPI on version tags through trusted publishing or an API token, and skips publishing when neither is configured.
- CI jobs for Python 3.10 to 3.13 with all extras, a minimal-dependency run, PostgreSQL with pgvector, the documentation build, and package checks.
Changed
MissingDependencyErroris raised for missing optional packages. It subclasses bothPersianRagErrorandImportError.RAGPipeline.queryraisesTypeErrorwhen given an async model; useaqueryinstead.- The
allextra now installs every optional integration. - README rewritten with an extras table, usage guides, and a Persian summary.
v0.1.0
Added
- Python package
persian_ragfor Python 3.10 and newer. - Persian normalization: Arabic and Persian letters, ZWNJ, digits, optional diacritics, and punctuation.
- Sentence splitting, tokenization, and fixed, sentence, and recursive chunking.
- Embedder protocol with hashing, sentence-transformers, and OpenAI-compatible adapters.
- In-memory cosine store and an optional FAISS adapter.
- BM25, dense retrieval, and reciprocal rank fusion.
RAGPipelinewith a caller-supplied LLM callable.persian-rag ingestandpersian-rag querycommands, plus a JSON index.- Unit tests, Ruff, mypy, and a GitHub Actions workflow.