3) Собственно RAG - максимально наколеночный, но работающий вариант
#!/usr/bin/env python3
from llama_index.retrievers.bm25 import BM25Retriever
from llama_index.llms.ollama import Ollama
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core import load_index_from_storage, StorageContext
from llama_index.core import Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core.retrievers import QueryFusionRetriever
from llama_index.core.retrievers.fusion_retriever import FUSION_MODES
HF_TOKEN = "Ваш токен на Hugging Face"
embeddings = HuggingFaceEmbedding(
model_name="google/embeddinggemma-300m",
query_instruction="task: search result | query: ",
text_instruction="title: none | text: ",
token=settings.HF_TOKEN,
)
llm = Ollama(
model="qwen3:latest",
request_timeout=120.0,
base_url="АДРЕС ВАШЕЙ ОЛЛАМЫ",
thinking=False,
)
Settings.embed_model = embeddings
Settings.llm = llm
loaded_bm25_retriever = BM25Retriever.from_persist_dir("./bm25_retriever")
# query_engine = RetrieverQueryEngine.from_args(retriever=loaded_bm25_retriever, llm=llm)
storage_context = StorageContext.from_defaults(persist_dir="./vector")
index2 = load_index_from_storage(storage_context)
vector_retriever = index2.as_retriever(similarity_top_k=2)
# QUERY_GEN_PROMPT = (
# "You are a helpful assistant that generates multiple search queries based on a "
# "single input query. Generate {num_queries} search queries, one on each line, "
# "related to the following input query:\n"
# "Query: {query}\n"
# "Queries:\n"
retriever = QueryFusionRetriever(
[vector_retriever, loaded_bm25_retriever],
similarity_top_k=2,
num_queries=4, #Делать 4 варианта перефразирования, поставьте 1 для отключения перефразирования
mode=FUSION_MODES.RECIPROCAL_RANK,
use_async=True,
verbose=True,
# query_gen_prompt="...", # we could override the query generation prompt here
)
query_engine = RetrieverQueryEngine.from_args(retriever=retriever, llm=llm)
r = query_engine.query(query)
print(r)