Галоўная / Артыкулы / RAG толькі для VPC на адзінай EC2: Ollama, Qdrant і LangChain

RAG толькі для VPC на адзінай EC2: Ollama, Qdrant і LangChain

Заменіце племянскія знаёмства на асистента-рукаводзіцель, які цитуецца і не дазволяе дакументам паказацца за межы вашага акаунта AWS — тры контейнеры на GPU EC2.

1723 слоў

Проблема неофіцыйскага істочніка знаёмасцей

У кожной інжынерскай арганізацыі є людзі, які ведаюць адпаведныя адказы: як працюе процес развяртання, што прыменяецца па правілах выпуску на час відсутнасці, чаму Kafka паважаецца кращым за SQS. Усё гэта працуе, пакуль гэтыя людзі не знаходзяцца у відпуску, не пераходзяць у іншыя команды, або калі новы спеціяліст патрабуе правду о 23:00 пад час інцыдэту.

Кращы варіант: кожны можа запытаць «Магчыма развяртваць у пятніцу?» і за секунды атрымаць задокументаваны адказ — падкрэплёны реальнымі інструкцыямі з адказам на запытанняі, з цитатай. Не проста дагадка. Не вымысел.

Адзін паказанне вплыў на дизайн: жадныя внутршнія дакументы не выходзяць за межы акаунта AWS. Ніякіх ключоў OpenAI. Ніякіх хоставаных вектарных БД. Усё должна працаваць у VPC на аднай машыне EC2.

Што вы атрымуеце

Просты ўжоць Streamlit для чату. Задайце запит; адкройце джэрынасы, каб пазнакаць, які файл і роздзел сталі адказам. Прыклад: даны пра залежнасці службы платэжа беруцца з deployment-runbook.md, а не стваруюцца вялікія імены хостаў.

Архітэктура — тры контейнеры

Команда docker compose up запускае:

version: "3.9"

services:
  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    ports:
      - "11434:11434"
    volumes:
      - ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    restart: unless-stopped

  qdrant:
    image: qdrant/qdrant:v1.18.2
    container_name: qdrant
    ports:
      - "6333:6333"
      - "6334:6334"
    volumes:
      - qdrant_data:/qdrant/storage
    environment:
      - QDRANT__SERVICE__ENABLE_CORS=true
    restart: unless-stopped

  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: rag-app
    ports:
      - "8501:8501"
    environment:
      - OLLAMA_BASE_URL=http://ollama:11434
      - QDRANT_URL=http://qdrant:6333
      - COLLECTION=company_docs
      - EMBED_MODEL=nomic-embed-text
      - LLM_MODEL=llama3.1:8b
      - S3_CORPUS_BUCKET=${S3_CORPUS_BUCKET}
      - S3_CORPUS_PREFIX=${S3_CORPUS_PREFIX:-corpus/}
      - AWS_REGION=${AWS_REGION:-us-east-1}
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-}
    volumes:
      - corpus_data:/app/corpus
      - ./scripts:/app/scripts
    depends_on:
      - ollama
      - qdrant
    restart: unless-stopped

volumes:
  ollama_data:
  qdrant_data:
  corpus_data:
  • Ollama — локальны модэль для імбеддынгу плюс модэль чату (на прыклад, llama3.1). Няма ключаў API, няма лічэння за кожны токен.
  • Qdrant — храніць вектары частак і швядка выкарыстоўвае іх для пошуку найбліжэйшых суседзей.
  • LangChain — процес пошуку → пакаванне контэксту → генераванне адказа, з цітатамі.

Усе гэта знаходзится на экземпляры GPU EC2 унутранік VPC, таму корпусы дадзеных ніколі не пераходзяць межы.

Падключэнне схемы запита

Ланцоўка у стылі LCEL выконвае пошук, форматаванне і стварэнне запыту для локальнага модэля чату:

from operator import itemgetter
from langchain_core.runnables import RunnableLambda, RunnableParallel

chain = RunnableParallel(
    question=itemgetter("question"),           # pass question through
    docs=itemgetter("question") | retriever,   # embed + search Qdrant
).assign(
    answer=(
        {"context": itemgetter("docs") | RunnableLambda(format_docs),
         "question": itemgetter("question")}
        | prompt_template    # inject into system/human message
        | llm                # send to Ollama
        | str_parser         # extract text from response
    )
)

Процес адаптавання захоўваецца лексычна ўрожайным, як вы яго налаштавалі; генераванне застаецца на платформе Ollama. Цітаты беруцца з метаданых, якія вяртае Qdrant.

Прымэнне дадзеных і прыміткі з аператывных задач

Падкладзіце файлы у формате markdown і інструкцыйныя кнігі ў шлях прымэння дадзеных, разбійце іх на часткі, включыце ў местную модель эмбеддінгу, а пасля — апдэйтуйце ў Qdrant. Перзапускайце процес, калі змянююцца дакументы. Следзіце за викорыстоўванням диска для модэляў, памяці GPU для адночасных запытоў, а таксама за групамі безпекі, каб толькі VPN чы бастіон моглі дасягнуць Streamlit і Qdrant.

Чаму такі падход ўзяў перавагу для внутрашняй інформацыі

Вы жертвуеце максимальным качаннем модэля зарады гравітасіі дадзеных і контролю витак. Для запытанняў на кшталт «Што сказана ў нашай інструкцыйной кнізе?» такая жертва є правильная. Калі Аарона няма, інструкцыйная кніга все равно дае адпаведныя адказы — а цітата паказвае, дзе можна пераканацца.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўваце адну локацію для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўваце адну локацію для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўваце адну локацію для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўваце адну локацію для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўваце адну локацію для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, перагляд стану і адзін месца для змены модэлей. Самэўсёдзе — гэта спосаб, як внутрашні інструменты выжываюць пад час взаімадзеяння з рэальнымі графікамі выклікаў.

Зробіце процес развярання нудным: наладжыце складанне, перагляд стану і адзін месца для змены модэлей. Самэўсёдзе — гэта спосаб, як внутрашні інструменты выжываюць пад час взаімадзеяння з рэальнымі графікамі выклікаў.

Зробіце процес развярання нудным: наладжыце складанне, перагляд стану і адзін месца для змены модэлей. Самэўсёдзе — гэта спосаб, як внутрашні інструменты выжываюць пад час взаімадзеяння з рэальнымі графікамі выклікаў.

Зробіце процес развярання нудным: наладжыце складанне, перагляд стану і адзін месца для змены модэлей. Самэўсёдзе — гэта спосаб, як внутрашні інструменты выжываюць пад час взаімадзеяння з рэальнымі графікамі выклікаў.

Зробіце процес развярання нудным: наладжыце складанне, перагляд стану і адзін месца для змены модэлей. Самэўсёдзе — гэта спосаб, як внутрашні інструменты выжываюць пад час взаімадзеяння з рэальнымі графікамі выклікаў.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўваце адну локацію для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўваце адну локацію для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўваце адну локацію для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўваце адну локацію для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўваце адну локацію для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі выклікаў.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі выклікаў.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі выклікаў.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі выклікаў.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі выклікаў.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Зробіце процес развярання нудным: наладжыце складанне, пераконтролюйце стан і выкорыстоўвайце адну пазічку для замены модэляў. Самэ гэта і дапамагае внутршнім інструментам выжыць пад час вярагання з рэальнымі графікамі работы.

Абяцка: даны ніколі не выходзяць за межы VPC

Нэпрыемныя правілы паўтарацельна вплывалі на выбор кожнага прадавца. API, сумесныя з OpenAI і керованыя, былі адхілены. Векторныя базы дадзеных, якія хоставаліся звычайна, таксама адхілены. Нават «вялікія» завантажэння на прыемную стадію былі заборонены. У такіх умовах засталася толькі адна ентыцэтка EC2 з GPU, файл compose і правілы IAM/групы безпекі.

Якщо ваша юрыдычная каманда не можа чытка практычна адзначыць межы ENI ў EC2, то такая архітектура не падходзіць вам. Якщо ж яна можа гэта зробіць, вы будете мячыцца прававымі праўамі, не падаючы PDF-файлы трэцім сторонам.

Падробныя відомасці працэсу практычнага перадачы дадзеных

Інструкцыі і правілы рашэння проблем зберагаюцца у формате markdown у спецыяльным каталогу. Заданне дзеліць іх на часткі, якія перакрываюць адзін другога, вбудовывае іх за дапамою локальнага модэлю embedding через Ollama і дадзеўляе даны ў Qdrant разам з метааданымі пацёка і роздзела. У разе неудачы трэба абараніць дадзеўленне для таго файла, а не проста безшумна паспусціць напалову документ з правіламі.

Павтараць умяшчэнне, калі змянюецца хеш файлу. Якщо можна адзінакаваць змяны па шляху, утримайцеся ад павтаральнага умяшчэння всего корпусу пасля кожных незначных змян.

Працэўнае сталяванне пад час запытку

Програма Streamlit адправляе запытку пользователя да прыстрою для пошуку, налаштаванага з малым значэнням k. Атрыманыя тэксты фарматуюцца ў запрошэнне, якое прыказвае модэлю чату адпавядаць толькі на основе контексту і адмовіцца, калі контекст недастатковы. Цитаты прадаюцца з метаданых, ўжо калі чалавек можа ачынуць конкрэтны раздзіл інструкцый.

Гэтая практыка адмовы, калі контекст недастатковы, мае большое значэнне, чым настройкі температуры. Плавны бессэнс з фальшывай цітатай ўжо гorsы, чым «Я не бачу гэтага ў інструкцый».

Варыянты абякання, якія трэба узяць за ўвагу

Проблемы з выкарыстоўваннем памяці GPU, калі хтось запускае большы модель чату без падвышэння розмеру інстанцы. Адбываецца зростанне дыска Qdrant, якщо запускаюцца бінарныя файлы-непатрэбнікі. Старыя адпаведзення пасля змены процэса, якія ніхто не перзапускае. Стакі Compose, якія прыўязуюць порты да 0.0.0.0 у публічнай сабетце — трэба яныя заставіць прыватнымі.

Адпаведальная аддзелаўцы должны ведаць, як перазапускаць Ollama, перабудаваць том Qdrant з адпаведных файлаў у формате markdown і пераканацца, што адпаведзення на ключовыя запитанні ўсё яшчэ атрыбуюцца правым файлам.

Як выглядае «завершанне»

Новы працавнік вось на другі дзень можа ставіць запытанні пра развяртанне без неабходнасці звернуцца да Аарона. У адпаведзеннях паказваюцься шляхі. Межы VPC находзяцца пад перагледам. Косты складаюцься з адной інстанцы EC2 плюс прыёмнае сховішча — гэта прыведама вялічына. Гэтага дастаткова для внутраньняга асистента з ведамасцямі; прабавы ўжо кращых модэляў трэба робіць толькі пасля таго, як атрыбуцыі будуць надзеянымі.