Галоўная / Артыкулы

Пুнная локальная PDF RAG з Лангчэйн, Оллама і Крома

Цалкам локальны ўтварэнне для PDF RAG: LangChain прыймае файлы, Ollama іх інтэгруе, Chroma зберагае вектары, а адпаведзі беруцца без падключэння да воблака, без якіх-лібо ключаў API.

Выдавец: REACTAPP.TOP5 хв чытання1111 слоў

Крыніцы: 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 пішчыць адпаведны адказ.

Две фазы дапамагаюць залічваць вітраты правядзебна:

  1. Прыйманне — адна раз (або калі зменяюцца дакументы): парсаванне, урэзкаванне, эмбедынг, зберагчыце
  2. Пошук — кожны запыт: найболей значымыя урэзкі стаюць кантэкстам для 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 скасоўвае неабходнасць налажвання графа. Для прыватных корпусаў дэтых трох падступаў достатнек, каб створыць корыснага асістэнта для обработкі дакументаў без неабходнасці плата за выкарыстоўванне воблака чы адправкі дадзенаў.