RAG толькі для VPC на адзінай EC2: Ollama, Qdrant і LangChain
Асістэнт для керавання RAG, які працуе толькі ў VPC, на аднам GPU EC2: Ollama, Qdrant і LangChain у трохце кантэйнерах, цітаванне адпаведных адказоў, і жадных дакументаў, якія выйдзе з вашага акаунту AWS.
Крыніцы: Self-Hosted RAG on AWS EC2: Qdrant, Ollama, and LangChain with Docker Compose
Проблема неофіцыйскага істочніка знаёмасцей
У кожной інжынерскай арганізацыі ёсць людзі, які ведаюць адпаведныя адказы: як працюе працэс развяртання, што прыменяецца па правілах выпуску на час відсутнасці, чаму 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 плюс прыёмнае сховішча — гэта прыведама вялічына. Гэтага дастаткова для внутраньняга асістэнта з ведамасцямі; прабавы ўжо крашчых модэляў трэба робіць толькі пасля таго, як атрыбуцыі будуць надзеянымі.