Пুнная локальная PDF RAG з Лангчэйн, Оллама і Крома
Цалкам локальны ўтварэнне для PDF RAG: LangChain прыймае файлы, Ollama іх інтэгруе, Chroma зберагае вектары, а адпаведзі беруцца без падключэння да воблака, без якіх-лібо ключаў API.
Крыніцы: Implement RAG with Langchain and local Ollama models
Створыце абсалютна локальная паіплайн RAG для PDF-файлаў за дапамогай LangChain, Ollama і ChromaDB — размовляйце з дакументамі без вікорыстання хмарных API і без выйшчых з апарата дадзенняў.
Чаму локальны варыянт мае значэнне
Хмарныя LLM-мадэлі ўдобныя, але кожны запіт перадае тэкст праз чужую сетка. Прававыя контракты, медычныя дакументы і внутрашняя статыстыка часта не можу прыйміць такі компроміс. Локальная схема абэруе рысы безпекі, заўсёды дазваляючы адпаведзяць на запіты на натуральнай мове на базе савых файлаў.
Што вы отрымаеце
- Прыём PDF-файлаў у стойкі сховішча вектараў
- Адпаведзь на запытанні на натуральнай мове, апарацыйныя ў тых дакументах
- Работа без інтэрнэту пад час аналізу — не трэба API-клячоў пасля завантажэння модэлей
Стак: LangChain для кінцевагання, Ollama для локальных чатоў і эмбедынгаў, ChromaDB як сховішч для вектараў.
Архітэктура
Шлях прыймання: байты PDF прайходзяць у завантажувач на базе PyPDF, далей адбываецца ўрэзкаванне, пасля чаго Ollama вставляе кожны урэзок у Chroma.
Шлях запіта: запыт прайходзіць да механізма пошуку, адпаведныя урэзкі стаюць кантэкстам, а локальная мадэль чатоў Ollama пішчыць адпаведны адказ.
Две фазы дапамагаюць залічваць вітраты правядзебна:
- Прыйманне — адна раз (або калі зменяюцца дакументы): парсаванне, урэзкаванне, эмбедынг, зберагчыце
- Пошук — кожны запыт: найболей значымыя урэзкі стаюць кантэкстам для LLM
Вы плаціце за эмбедынг, калі зменяецца контэнт; інтэрактывныя запыты застаюцься шырокімі.
Прыяўнія выканання
З'ядзіце Ollama і завантажыце мадэлі, якія тут вікорыстоўваюцца:
ollama pull embeddinggemma:latest # embedding model
ollama pull gemma4:latest # chat model
gemma4 адаптаваны пад заданыя інструкцыі. Калі хочаце меньшых выкарыстоўвання рэсурсаў, спробуйце gemma2:2b; для сільнейшага аналізу выкарыстоўваюце gemma4:27b — адпаведна адкорэгуйце строкі налаштоўкаў.
Настройкі праекта
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Ключовыя пакеты з спісу выкарыстоўвання:
langchain
langchain-chroma
langchain-community
langchain-ollama
langchain-text-splitters
pypdf
chromadb
python-dotenv
Можна зменіць стандартныя настройкі за дапамогою сэраўыска, не правячы коду:
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=gemma4:latest
OLLAMA_EMBED_MODEL=embeddinggemma:latest
Працэс прыемкі дадзеных (src/ingest.py)
Завантажэнне дакументаў
def load_documents(pdf_path: str | Path) -> list:
path = Path(pdf_path)
loader = (
PyPDFLoader(str(path))
if path.is_file()
else PyPDFDirectoryLoader(str(path))
)
return loader.load()py
Адны памочны код здольны обрабацваць або адні файлы, або адну дырэктарыю. Завантажвачы LangChain у будзьму выпадку вяртаюць аднаковы спіс Document.
Разбіўка на часткі
def split_documents(documents: list) -> list:
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
)
return splitter.split_documents(documents)
RecursiveCharacterTextSplitter выбірае спачатку роздзелы, потым запэўнення, а пасля — розбітку на словы, каб семантычныя межы засталіся. Надпаку з 200 сімваламі дазволяе заставіць запэўнення, якое пераходзіць межу, прысутным у обох суседніх фрагментах, чыя вырашае прычыны неправільнага адналёгання на краях.
Уключэнне і зберэжэння
def build_vector_store(chunks: list) -> Chroma:
embeddings = OllamaEmbeddings(model=EMBEDDING_MODEL, base_url=OLLAMA_BASE_URL)
VECTOR_STORE_DIR.mkdir(parents=True, exist_ok=True)
return Chroma.from_documents(
documents=chunks,
embedding=embeddings,
collection_name=COLLECTION_NAME,
persist_directory=str(VECTOR_STORE_DIR),
)
Ollama выдае эмбедынгі локальна на порту 11434. Chroma зберагае іх у катэгорыі vector_store/ (SQLite плюс файлы індэкса HNSW), таму перэзапуск працэса не вымагае повнага павтарэння працэсу уключэння.
Ланцюг адналёгання (src/retrieval.py)
LangChain LCEL складае крокі за дапамою аператара |.
Шаблон запіту
RAG_PROMPT = ChatPromptTemplate.from_messages([
(
"system",
"You are an assistant that answers questions based on the provided context "
"from PDF documents. Use only the information in the context to answer. "
"If the answer is not in the context, say so clearly.\n\nContext:\n{context}"
),
("human", "{question}"),
])
Сістэмныя паведамленні прыкрэпляюць адказы да знятых кантэкстаў — гэта основны заход RAG проты халюцынацый, якія можуць выйсці толькі з адналёгання на прадзейнаванне.
Стварэнне ланцюга
def build_rag_chain(k: int = 4):
store = load_vector_store()
retriever = store.as_retriever(search_kwargs={"k": k})
llm = ChatOllama(model=MODEL_NAME, base_url=OLLAMA_BASE_URL)
return (
{"context": retriever | _format_docs, "question": RunnablePassthrough()}
| RAG_PROMPT
| llm
| StrOutputParser()
)
Злева напраўо: рэтрывер выбірае k найболей схожых фрагментаў на аднойчыні сэмабільнасці, дапаможнікі фарматуюць гэтыя фрагменты ў адну строчку кантэксту, шаблон запіта з’еднае кантэкст з пытаннем карыстальніка, а ChatOllama генеруе адпаведзь.
Інтэрактыўны цыкл запітаў
# Index a directory of PDFs (default: data/pdfs/)
python main.py ingest
Просты CLI (або HTTP-рабер) запускае ланцуг аднойчы і обслужвае запіты пакуль вы не завершыце працу. Залічвайце, што k можна налаштаваць, ўсёлякім чынам зменшуючы або падвышаючы розмер кантэксту зарады змены часу адпаведзі.
Работа з початку да канца
# Index a specific file
python main.py ingest --path /path/to/contract.pdf
# Ask a one-off question
python main.py query "What are the payment terms?"
# Interactive session
python main.py chat
Наведзіце пункт запоўнення на папку з PDF-файламі, пераканаўцеся, што каталог для зберагача вектараў запоўнены, а потым выконайце запіт. Усё — аднойчыні сэмабільнасці, вектары, генераванне — застаецца на localhost.
Вывык
Локальныя RAG-сістэмы большэй не ўважаюцца чымось экзотычным. Ollama сапраўджае модэлі, Chroma зберагае вектары, а LangChain скасоўвае неабходнасць налажвання графа. Для прыватных корпусаў дэтых трох падступаў достатнек, каб створыць корыснага асістэнта для обработкі дакументаў без неабходнасці плата за выкарыстоўванне воблака чы адправкі дадзенаў.