Практычныя прыказкі: стварэнне локальнага каналу RAG высокай якосці для прымення ў практыцы — 100% безкоштовна, без…
Практычныя прыказкі: стварэнне локальнага каналу RAG высокай якосці для прымення ў практыцы — 100% безкоштовна, без дагавораў, пераканальвання і можлівасцяў для вставкі коду для команд, якія выкарыстоўваюць гэты патэрн.
У гэтым керавані зноў ствараецца парадокс ад сыр'ёў да рабочай системы для: стварэння локальнага каналу RAG высокай якосці — 100% безкоштовна, без патрэбы ў хмарах. Акцэнт ставіцца на практычныя крокі, чысткія перакананні та код, які можна проста дадаць у репозытарый без неабязковасці здогадвацца пра мету. У стадзіі агляду неабходна практычна визначыць інпуты, адпаведальную особу за крок та критэрыя завершэння прычынамі перад зменым коду. Аператары должны магчымае перадзванаць крок з вядомай точкі контролю без неабязковасці здагадвацца пра схованы стан. Неабходна адначасова задокументаваць шлях успеху та шлях вяснавання. Перапрыбуткі, людзкія перакананні та обробка некоректных паведамленняў є частью продукту, а не чымсь, што дадаецца пазней.
Чаму гэта важна
Калі працюеце над этапам «Чаму гэта важна», спачатку запісайце умовы кантракту: неабяжлівыя даны, сігнал успеху і тое, што выходзіць пад частыя неудачы. Такі список контроля дапамагае заліцьварыць пазнейшыя змены ў кодзе. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшоў, неудача должна вказваць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцужок задач. Перад налаштаваннем запитоў пераканайцеся, як працуе система з воспамінанням на фіксаванай сэтцы запитаў. Частая зміна запитоў рэдка калі вярнайце слабкую эфектыўнасць выкарыстоўвання інформацыі.
Полны тэхнічны стак
Калі працюеце над стадзіяй «The Complete Tech Stack», спачатку запісайце контракт: неабяжлівыя даннэ, сігнал успеху і тое, што выходзіць у разе частковага нэуспеху. Такі список контроля дапамагае залічыць пазнейшыя змены коду чыстымі. Спрыятліваце гэтую стадзію як контракт межу вхіднымі даннэмі і перакананымі выходнымі результатамі. Даўце назвы артыфактам, задаце критэрыя успеху і адмовіцеся ад тыхоўскага частковага завершэння. Замерыўце рэкалі на фіксаванай сэтке запытаў прычым падлашоўвання прапаза. Частая змена прапаза рэдка калі вярнуе слабую якасць адзысквання інформаціі.
Прыямыя прычынкі
Калі працюеце над стадзіяй «Прыёмныя умовы», спачатку запісайце «контракт»: неабяжлівыя данні, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список пераконвае ў тым, што пазнейшыя змены коду будуць чыстымі. Запісвайце час выканання і кост токена або запыту праза функцыйнальнымі рэзултатамі. Відразы коста з самага пачатку запобегае неспакоўным рахункам, калі працэс пераходзіць з дэмаверсіі ў спяльныя среды. Замерьце ступень воскрэсення інформацыі на фіксаванай сэтке запытаў прычым регулюванню прапозыцый. Частае змены прапозыцый рэдка калі-небудзь выправляюць слабыя аспекты пошуку інформацыі. Калі працюеце над стадзіяй «Прыёмныя умовы», спачатку запісайце «контракт»: неабяжлівыя данні, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список пераконвае ў тым, што пазнейшыя змены коду будуць чыстымі. Аддокументавайце як «шчаслівы» шлях, так і шлях вяснавання. Перапрыбуткі, людзкія контралі і обработка некоректных паведамленняў ёсць часткай продукту, а не пазнейшым дапрацоўкам.
Частка 1 — Наладжэнне среды
Этап налагоджэння супакоўкі ў частцы 1 працюе найэфектывней, калі яго спрыяваць як мерыемую структуру. Зафіксавайце адну ідеальную версію, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Валідзіце невялікія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выходзіць, прычына неудачы павінна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач. Раздзеліце правілы частковай обработкі дадзеных ад правіл ўтрымання іх. Змена адных не павінна вымагаць перапісву іншых, калі зменяюцыся показнікі якосці.
Крок 1: Стварыце проект
Першы шаг – стварэнне сцэны – работае найкраща, калі яго спрыяюць як до мерыям падлеглую паверхню. Зафіксавце адны «золаты» прымер, адну справу з бягамі та прыметкі па адварцыю перш чым расширваце масштабы. Спрыяйце гэтам шагу як кантракту межаў уваходных дадзеных і перакананыя выходныя рэзультаты. Даўце назвы артыфактам, задаце критэрыя успеху та адмовіцеся ад мовчанкавага частковага завершэння. Раздзеліце політыку часткавага абрабатвання дадзеных ад політыкі ўтрымання іх. Змена адной з яных не павінна прымусваць перапісванне другой, калі зменяюцыся паказнікі якосці.
mkdir local-rag
cd local-rag
uv init
Шаг 2: Стварэнне та актывацыя віртуальной среды
Крок 2 «Стварыць і размістыць» працуе найэфектывней, калі яго розглядаць як параметр, які можна вымерыць. Зберагчыце адны ідеальны прыклад роботы, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану, перш чым расширваць масштабы. Запісвайце час выканання задач і кост токеноў або запытаў разам з функцыйнальнымі рэзултатамі. Відразы костаў з самага пачатку запобегае неспакойным рахункам, калі процес пераходзіць з дэмаверсіі ў спяльныя среды. Раздзеляйце правілы частковага обробкі дадзеных і правілы ўтрымання інформацыі. Змена адных не павинна вымагаць перапісвы іншых, калі зменяюцца паказнікі якасці.
uv venv
.venv\Scripts\activate
Крок 2 «Стварыць і размістыць» працуе найэфектывней, калі яго розглядаць як параметр, які можна вымерыць. Зберагчыце адны ідеальны прыклад роботы, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану, перш чым расширваць масштабы. Дакументавайце як шлях успеху, так і шлях вярнэння да нормальнага стану. Перапрыбуткі, людзкі контроль і обробка некоректных паведамленняў є частью продукту, а не етапамі далейшай налады.
Крок 3: Установіць усе залежнасці
Для трэцьяго крока – установкі ўсіх элементаў на пэўны ўровень – неабходна заздалегідь вызначыць параметры входных дадзеных, адпаведальнага за крок і критэрыя завершэння працы перад змінайом коду. Аператары должны магчымае перзапускать крок з вядомай точкі контролю, не прабуючы спадарацца пра схованы стан. Лепш выбіраць маленькія, тэставаныя елементы замест большых скрыптов. Калі крок не выконваецца, прычына неудачы должна вказываць на адну конкрэтную прычыну, а не на заплутаную структуру процеса. Прытамульвайце тыя часткі тексту, якія фактычна лежаць у падставе адпаведнай адказы. Без ціх цитатаў аператары не зможуць разлічыць галюцинацію ад працягу індэксавання.
uv add google-genai pypdf chromadb rich python-dotenv huggingface_hub fpdf2
Крок 4: Стварэнне структуры проекта
Для крока 4 «Стварыць этап» неабяжна пазначыць вхідныя даны, адпаведальнага за крок і критэрыі завершэння пры перадзеяванні коду. Аператары должны магчымаць перзапуск крока з вядомай точкі контролю, не падозрываючы прыхованы стан. Спрыяйце цэму этапу як кантракту межа вхіднымі данымі і перакананымі выходнымі рэзультатамі. Дайце назвы артыфактам, пазначыце перакананні успеху і адмовіцеся ад беззвучнага частковага завершэння. Апісуйце тыя часткі, якія фактычна лежалі в основе адпаведнай адказы. Без ціх апісаў аператары не зможуць разлічыць галюцинацію ад прасоў у індэксаванні.
mkdir pdfs
mkdir pdfs\versions
type nul > local_rag.ipynb
type nul > .env
type nul > .gitignore
local-rag/
├── .venv/ ← virtual environment (never commit)
├── pdfs/ ← drop your PDFs here
│ └── versions/ ← test PDFs for CDC testing
├── chroma_db/ ← auto-created on first ingest
├── memory_checkpoints/ ← auto-created on first memory session
├── staleness_registry.json ← auto-created
├── chunk_registry.json ← auto-created
├── local_rag.ipynb ← your notebook
├── .env ← API keys (never commit)
├── .gitignore
└── pyproject.toml
Крок 5: Наладжыць ключы API
Для стадіі «Настроўка API» па кроку 5 неабходна перад змянай коду вказацьці інпутаў, адпаведальнага за крок і крэтарыяў завершэння. Аперацыйныя працавнікі должны магчымае запускаць крок з вядомай точкі контролю, не падозрываючы прыхованы стан. Запісваць час выконання і кост токенаў або запытаў разам з функцыйнаімі рэзультатамі. Відразлівая видавальнасць костаў з самага пачатку запобегае неспакойным рахункам, калі процес пераходзіць з дэмовай среды ў спакульнаныя сераверы. Указваць часткі тексту, якія фактычна ляглі в основу адпаведнай адказы. Без цых цітатаў аперацыйныя працавнікі не можуць разлічыць галюцинацію ад прасоў у індэксаванні. Для стадіі «Настроўка API» па кроку 5 неабходна перад змянай коду вказацьці інпутаў, адпаведальнага за крок і крэтарыяў завершэння. Аперацыйныя працавнікі должны магчымае запускаць крок з вядомай точкі контролю, не падозрываючы прыхованы стан. Аддзеўна задокументаваць шлях успеху і шлях вярнення. Перапрыбуткі, людзкія контролі і обработка некоректных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней.
GEMINI_API_KEY=your_gemini_key_here
HF_API_KEY=your_huggingface_token_here
.env
chroma_db/
memory_checkpoints/
staleness_registry.json
chunk_registry.json
__pycache__/
.venv/
*.pyc
Шаг 6: Налаштаванне VS Code
Працюючы над шагам налаштавання, спачатку запішыце умовы працы: неабяжлівыя даны, сигнал успеху і тое, што выходзіць, калі адбываецца частковая памылка. Такі список контролю дапамагае залишацца чыстым пад час будучых змян у кодзе. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь шаг не выйшаў, памылка должна вказываць на адну конкрэтную прычыну, а не на заплутаную структуру задач. Перад налаштаваннем запитоў пераканайцеся, што система правільна адпавядае на фіксаваныя запитанні. Часта змена запитоў рэдка калі-небудзь выправляе слабую якасць адпаведзей.
Ctrl+Shift+P → Python: Select Interpreter → .venv\Scripts\python.exe
Частка 2 — Падробны аналіз основнай структуры
Калі працуеце над стадзіяй «Core Pipeline», часткай 2, спачатку запісаце кантракт: неабяжлівыя вхідныя даны, сигнал успеху і тое, што выходзіць у разе частковага невыпання. Такі список контролю дапамагае заліцьварыць пазнейшыя змены коду. Спрэтавайцеся да гэтай стадзіі як да кантракта межа вхіднымі данымі і перакананымі выходнымі рэзультатамі. Даць назвы артыфактам, задаць критэрыя успеху і не падзеўляйцеся частковым завершэнням без паведамлення. Змяроўваце рэкалі на фіксаванай сэтке запытаў прычым падбір прамптав. Частае змена прамптав рэдка калі вярнуе слабую эфектыўнасць адзысквання інформаціі.
Клетка 1 — Залежнасці (внутрь нотбука)
Калі працуеце над Залежнасцямі Клеткі 1 унутрь стадыі, спачатку запісайце контракт: неабяжлівыя вхідныя даны, сигнал успеху і тое, што выходзіць пад частковым невясненням. Такі список пераканаець у тым, што пазнейшыя змены коду будуць чыстымі. Запісвайце час выконання і кост токена або запыту празаўседле з рэзультатамі функцыянальнай працы. Візуабельнасць костаў з самага пачатку запобегае неспакойным рахункам, калі парадокс пераходзіць з дэмаверсіі ў спяльныя среды. Замерьце рэткі адзыв на фіксаваны набор запытаў прычым рэгулюванню прапазаў. Частыя змены прапазаў рэдка калі-небудзь вылечваюць слабую систему адзыва.
# Run once inside the notebook if uv add was not used externally
# %pip install google-genai pypdf chromadb rich python-dotenv huggingface_hub fpdf2
Калі працуеце над Залежнасцямі Клеткі 1 унутрь стадыі, спачатку запісайце контракт: неабяжлівыя вхідныя даны, сигнал успеху і тое, што выходзіць пад частковым невясненням. Такі список пераканаець у тым, што пазнейшыя змены коду будуць чыстымі. Дакументавайце як «шчаслівы» парадокс, так і парадокс вяснавання. Перапрыбуткі, людзкія контралі і обработка нераспакаваных паведамленняў ёсць частью продукту, а не пазнейшым дапрацоўкам.
Cell 2 — Канфігурацыя
Этап канфігурацыі Cell 2 дае найкращыя рэзультаты, калі яго спрытваць як меравальную плошчу. Зберагачыце адна ідеальная версія, адзин случай неудачы і прыметкі па поверненню да пачатковага стану пры расшырэнні масштаба. Вядзейце прывялікія, тэставальныя елементы замест большых скрыптов. Калі якісь крок не выйшае, прычына неудачы павінна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач. Раздзеляйце правілы часткавання інфармацыі ад правіл яе выявлення. Змена адных не павінна прымусваць перапісванне іншых, калі змянююцца паказателі якосці.
import os
from dotenv import load_dotenv
load_dotenv()
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "")
EMBED_DIM = 768
HF_API_KEY = os.environ.get("HF_API_KEY", "")
GEMINI_EMBED_MODEL = "gemini-embedding-001"
HF_LLM_MODEL = "openai/gpt-oss-20b:groq"
CHROMA_DB_PATH = "./chroma_db"
COLLECTION_NAME = "local_rag"
CHUNK_SIZE = 800
CHUNK_OVERLAP = 120
TOP_K = 5
EMBED_BATCH_SIZE = 50
BATCH_SLEEP_SEC = 0.3
LLM_MAX_NEW_TOKENS = 1024
LLM_TEMPERATURE = 0.1
assert GEMINI_API_KEY, "❌ GEMINI_API_KEY not set"
assert HF_API_KEY, "❌ HF_API_KEY not set"
Cell 3 — Выяўленне тексту з PDF
Этап PDF-тэкста «Cell 3» працюе найкраща, калі яго розглядаць як вимерную паверхню. Зафіксавце адны ідеальны прыклад, адну справу з бягамі та запіс пра вярнэнне да пачатковага стану, перш чым расширваць масштабы. Разглядзіце гэты этап як кантракт межа вхіднымі даннымі та паверынутымі выходнымі рэзультатамі. Даце назвы артыфактам, задаце критэрыі успеху та не прабуйце прыймаць часткова завершаную роботу без паведамлення. Раздзеліце правілы часткавання ад правіл нараджэння дадзеных. Змена адных не павінна вымагаць перапісву іншых, калі зменяюцца паказателі якосці.
from pypdf import PdfReader
def extract_text_from_pdf(pdf_path: str) -> tuple[str, int]:
reader = PdfReader(pdf_path)
pages = []
for i, page in enumerate(reader.pages):
text = page.extract_text()
if text and text.strip():
pages.append(f"[Page {i + 1}]\n{text.strip()}")
return "\n\n".join(pages), len(reader.pages)
Cell 4 — Часткаванне за принцыпам «скользячага вікна»
Этап «Cell 4 Sliding Window» працюе найкраща, калі яго розглядаць як вимерную паверхню. Зафіксавце адны прыклад ідеальнага функцыонавання, адны прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Запісвайце часы выканання і косты токеноў або запытак праза функцыйнальныя рэзултаты. Відразлівае паказанне костаў з’являецца перашкоду неспакою, калі процес пераходзіць з дэмаверсіі ў спяльныя среды. Раздзеліце політыку часткавага оброблэння дадзеных ад політыкі ўтрымання іх. Змена адной з яных не павінна вымагаць перапісвання другой, калі зменяюцца паказнікі якосці.
def chunk_text(text: str) -> list[str]:
chunks, start = [], 0
while start < len(text):
end = start + CHUNK_SIZE
chunk = text[start:end].strip()
if len(chunk) >= 80:
chunks.append(chunk)
start += CHUNK_SIZE - CHUNK_OVERLAP
return chunks
Этап «Cell 4 Sliding Window» працюе найкраща, калі яго розглядаць як вимерную паверхню. Зафіксавце адны прыклад ідеальнага функцыонавання, адны прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Дакументавайце як шлях ідеальнага функцыонавання, так і шлях вярнэння да нормы. Перапрыбуткі, людзкія контрольныя пункты і обробка некоректных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней.
Cell 5 — Gemini Embeddings
Для стадіі Cell 5 Gemini Embeddings неабяжна практыка: перш чым зменіць код, неабяжна адзначыць вхідныя даны, адпаведальнага за шаг і критэрыі завершэння. Аперацыяныя працавнікі должны магчымаць перзапуск шага з вядомай точкі контролю, не падозрываючы схованы стан. Лепш выбіраць маленькія, тэставаныя елементы замест большых скрыптов. Калі шаг не выйшаў, прычына неабяжна адносіцца да конкрэтнай адпаведальнасці, а не да заплутанага ланца задач. Раздзеляйце стварэнне кліента ад цыклу перадачы паведамленняў, каб было можна змяніць прадаўцоў без перапісвання машыны стану размовы.
from google import genai
from google.genai import types
genai_client = genai.Client(api_key=GEMINI_API_KEY)
def embed_documents_batch(chunks: list[str]) -> list[list[float]]:
all_embeddings = []
for i, chunk in enumerate(chunks, 1):
result = genai_client.models.embed_content(
model=GEMINI_EMBED_MODEL,
contents=chunk,
config=types.EmbedContentConfig(
task_type="RETRIEVAL_DOCUMENT",
output_dimensionality=EMBED_DIM,
),
)
all_embeddings.append(result.embeddings[0].values)
return all_embeddings
def embed_query(text: str) -> list[float]:
result = genai_client.models.embed_content(
model=GEMINI_EMBED_MODEL,
contents=text,
config=types.EmbedContentConfig(
task_type="RETRIEVAL_QUERY",
output_dimensionality=EMBED_DIM,
),
)
return result.embeddings[0].values
Cell 6 — Хранэнне і выкарыстоўванне дадзеных у ChromaDB
Для стадіі зберагчэння ChromaDB у клетцы 6 неабяжна прадзефінаваць вхідныя даны, адпаведальнага за крок і критэрыі завершэння пры змяне коду. Аперацыйныя працавнікі павінны магчымаць перзапуск кроку з вядомай точкі контролю, не падозрываючы прыхованы стан. Спрыяйце гэтай стадіі як даговору межа вхіднымі данымі і перакананымі выходнымі рэзультатамі. Даўце назвы артыфактам, прадзефінаваць пераканання ў успеху і адмовіцеся ад тыхнай частковай рэалізацыі без паведамлення. Цитавайце тыя часткі, якія фактычна лежалі в основе адпаведнай адказы. Без цітатаў аперацыйныя працавнікі не зможуць адразліць галюцинацыю ад прасоўкі ў індэксаванні.
import uuid, chromadb
def get_collection():
client = chromadb.PersistentClient(path=CHROMA_DB_PATH)
return client.get_or_create_collection(
name=COLLECTION_NAME,
metadata={"hnsw:space": "cosine"},
)
def store_in_chroma(chunks, embeddings, doc_name):
collection = get_collection()
ids = [str(uuid.uuid4()) for _ in chunks]
metadatas = [{"source": doc_name, "chunk_index": i}
for i in range(len(chunks))]
collection.add(ids=ids, embeddings=embeddings,
documents=chunks, metadatas=metadatas)
return len(chunks)
def retrieve_context(query: str) -> list[dict]:
collection = get_collection()
query_embedding = embed_query(query)
results = collection.query(
query_embeddings=[query_embedding],
n_results=TOP_K,
include=["documents", "metadatas", "distances"],
)
chunks = []
for doc, meta, dist in zip(results["documents"][0],
results["metadatas"][0],
results["distances"][0]):
chunks.append({
"text": doc,
"source": meta.get("source", "unknown"),
"chunk_index": meta.get("chunk_index", -1),
"score": round(1 - dist, 4),
})
return sorted(chunks, key=lambda x: x["score"], reverse=True)
Клетка 7 — Адканаўленне прыемкі
Для стадіі працы Cell 7 Running Ingestion неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і критэрыя завершэння пры зміне коду. Аператары должны магчыма было перзапускаць крок з вядомай точкі контролю, не падозрываючы прыхованы стан. Запісваць час выконання і вартасць токена або запыту разам з функцыйнальнымі рэзултатамі. Відразы вартасці з самага пачатку запобегае неспакоўным рахункам, калі процес пераходзіць з дэмовай среды ў спяльныя сераўеры. Указваць тые часткі тексту, якія фактычна ляглі в основу адпаведнай адпаведзі. Без цых цитатаў аператары не можуць розразліць галюцинацію і прычыну, якая вынікла ў процэсе індексавання.
PDF_PATH = "./pdfs/attention.pdf"
raw_text, page_count = extract_text_from_pdf(PDF_PATH)
chunks = chunk_text(raw_text)
embeddings = embed_documents_batch(chunks)
stored = store_in_chroma(chunks, embeddings,
os.path.basename(PDF_PATH))
Для стадіі обробкы даных у Клетцы 7 неабяжна пазначыць вхідныя даны, адпаведнага адпаведальнага за крок і крэтыры завершэння пры змяне коду. Аперацыйныя працавнікі должны магчымаць перзапуск кроку з вядомай точкі контролю, не прабуючы выявіць схованы стан. Неабяжна задокументаваць як шлях успеху, так і шлях вярнення да нормальнага стану. Перапрыбуткі, людзкія перакрыцці та обробка некоректных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней.
Клетка 8 — LLM: gpt-oss-20b через HuggingFace
Калі працюеце над стадзіяй Cell 8 LLM gpt-oss-20b, спачатку запісайце угоду: неабяжлівыя даны, сігнал успеху і тое, што выходзіць у разе частковага неяксамоства. Такі список пераканальвае ў тым, каб пазнейшыя змены коду былі чыстымі. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок неяксамоўць, неяксамоства должны адносіцца да адной адпаведальнасці, а не да заплутанага ланцоўка. Зберагайце у кэшы стабільныя інструкцыі системы і схемы інструментаў. Перадзесланне ідэнтычных прамаўляючых частак — частая прычына витрацы ресурсаў.
from huggingface_hub import InferenceClient
hf_client = InferenceClient(api_key=HF_API_KEY)
def build_messages(query: str, context_chunks: list[dict]) -> list[dict]:
context_str = "\n\n---\n\n".join([
f"[Source: {c['source']} | Chunk #{c['chunk_index']} | "
f"Relevance: {c['score']}]\n{c['text']}"
for c in context_chunks
])
return [
{"role": "system", "content": SYSTEM_MSG},
{"role": "user", "content":
f"CONTEXT:\n{context_str}\n\nQUESTION:\n{query}"},
]
def generate_answer(messages: list[dict]) -> str:
completion = hf_client.chat.completions.create(
model=HF_LLM_MODEL,
messages=messages,
max_tokens=LLM_MAX_NEW_TOKENS,
temperature=LLM_TEMPERATURE,
)
return completion.choices[0].message.content.strip()
Cell 9–11 — The ask() Pipeline and REPL
Калі працюеце над этапам «Cell 9 11 The stage», спачатку запісайце умовы кантракту: неабяжлівыя даны, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список контроля дапамагае заліцьварыць пазнейшыя змены ў кодзе. Спрэцьвачваеце гэты этап як кантракт межа данымі і перакананымі выходамі. Дайце назвы рэзультатам, задаце критэрыя успеху і не прымайце часткова завершання без паведамлення. Змяркуйце рэгрэсію на фіксаванай сэтке запытанняў прычым падбір запытань. Частая змена запытань рэдка калі вядомае слабую ступеню адзысквання інформаціі.
query → embed_query() → ChromaDB cosine search → top-5 chunks
→ build_messages() → generate_answer() → printed answer
1. attention.pdf chunk #34 [██████████████████████░░░░░░░░] 0.7335
Частка 3 — Памяць размовы
Калі працюеце над стадзіяй «Пам’ятка размовы» часткі 3, спачатку запішыце контракт: неабяжлівыя даны, сигнал успеху і тое, што выходзіць у разе частковага невыпання. Такі список перакладзець пазнейшыя змены коду ў правільным напрамку. Запісвайце часы выканання і кост токеноў або запита праза функцыональныя рэзултаты. Відразлівасць костаў з самага пачатку запобегае неспакойным рахункам, калі працэс пераходзіць з дэмаверыянту ў спакульнае сераўысце. Замерьце спроможнасць адзычэння на фіксаванай сэтке запытаў прычым регулювання прапаза. Частыя змены прапаза рэдка калі вядуць да павышэння якасці адзычэння даных.
Проблема
Калі працюеце над стадзіяй рашэння проблемы, спачатку запісайце умовы: неабяжлівыя даны, сігнал успеху і тое, што выходзіць пад частыя неудачы. Такі список контролю дапамагае заліцьварыць пазнейшыя змены ў кодзе. Храніце настройкі парадульна ад коду прыемліка. Файлы сераўіса, хранальнікі секрэтных данных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куды аператары можаць адбавіць аудыт без неабяжлівага чытання всей структуры. Перад налаштаваннем запитоў пераканайцеся ў рэверыі на фіксаванай сэтке запытаў. Частае змены запытаў рэдка калі выправляюць слабую эфектыўнасць адзысквання інформаціі.
Рашэнне: ConversationMemory
Калі працуеце над стадзіяй ConversationMemory, спачатку запісайце умовы працы: неабяжлівыя даннэ, сигнал успеху і тое, што выканаецца у разе частковага невыпалення. Такі список контроля дапамагае заліцьварыць пазнейшыя змены коду.
class ConversationMemory:
def __init__(self, session_id: str = None):
self.session_id = session_id or datetime.now().strftime("%Y%m%d_%H%M%S")
self.filepath = os.path.join(MEMORY_DIR, f"{self.session_id}.json")
self.history = []
# Auto-loads if resuming an existing session
if os.path.exists(self.filepath):
self._load()
def add_turn(self, question: str, answer: str, chunks: list[dict]):
# Append user + assistant turns, checkpoint immediately
...
self._save()
def get_messages_with_history(self, query, context_chunks, system_msg):
# Injects last 6 Q&A pairs into the message list before the current turn
...
# New session
memory = ConversationMemory()
# Resume yesterday's session
memory = ConversationMemory("20260413_104959")
Turn 4 question: "How does that compare to what you said about the BLEU score?"
Turn 4 answer: "The context also reports a BLEU score of 28.4 for the
Transformer (big) on WMT 2014 English-to-German. This matches
exactly what I previously stated."
Частка 4 — Адстэйканне старасці, CDC і надаўанне вагі свежасці
Калі працюеце над стадзіяй 4 «Стежыць за занепадам», спачатку запісайце угоду: неабяжлівыя даны, сигнал успеху і тое, што выходзіць пад часты няудача. Такі список пераканальвае ў тым, каб пазнейшыя змены коду былі чыстымі. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшае, няудача должна вказваць на адну адпаведальнасць, а не на заплутаны процес. Перад налаштаваннем праблемаў пераканайце рэкалі на фіксаваным наборе запытанняў. Частае змена праблемаў рэдка калі вярнайце слабкую систему аднаходжэння інфармацыі.
Рэальная проблема
Калі працюеце над стадзіяй «Рэальная проблема», спачатку запісайце контракт: неабяжлівыя вхідныя даны, сігнал успеху і тое, што выходзіць у разе частковага невыпання. Такі список контроля дапамагае заліцьварыць пазнейшыя змены ў кодзе. Спрэцьвачайце гэтую стадзію як контракт межа вхіднымі данымі і перакананымі выходнымі рэзультатамі. Дайце назвы артыфактам, задаце критэрыя успеху і адмовіцеся ад тыхоўскага частковага завершэння. Замерайце рівень запамятовання на фіксаваным наборе пытанняў прычым перэналаштаванні запрошэнняў. Частае змены запрошэнняў рэдка калі вылечваюць слабкую структуру адзысквання інформаціі.
Стежыце за старэнням (Клетка 14A)
Калі працуеце над стадзіяй Staleness Tracking Cell 14A, спачатку запісайце умовы кантракту: неабяжлівыя данні, сигнал успеху і тое, што выходзіць пад частковыя неудачы. Такі список контроля дапамагае заліцвачыць пазнейшыя змены коду. Запісвайце час выканання і кост токена або запыту праз ці функцыйнальныя рэзултаты. Відразлівасць коста з самага пачатку запобегае неспакоўным рахункам, калі процес пераходзіць з дэмовай среды ў спакоўныя серавісы. Замерьце рэткую здатнасць на фіксаваным наборе запытаў прычыну налаштавання прапаза. Частыя змены прапаза рэдка калі вядуць да павышэння якасці выкарыстоўвання данных. Калі працуеце над стадзіяй Staleness Tracking Cell 14A, спачатку запісайце умовы кантракту: неабяжлівыя данні, сигнал успеху і тое, што выходзіць пад частковыя неудачы. Такі список контроля дапамагае заліцвачыць пазнейшыя змены коду. Дакументавайце як «вялікі успех», так і шлях вярнення да нормы. Перапрыбуткі, людзкія контрольныя пункты і обработка некоректных дадзеных ўжо є часткай продукту, а не пазнейшым дапрацоўкам.
def compute_file_hash(pdf_path: str) -> str:
sha = hashlib.sha256()
with open(pdf_path, "rb") as f:
for block in iter(lambda: f.read(65536), b""):
sha.update(block)
return sha.hexdigest()
CDC Engine (Cell 14B)
Этап Engine Cell 14B цэнтра CDC працюе наяўней, калі яго розглядаць як вимерную паверхню. Зафіксавайце адна «золатая» транскрыпцыю, адин прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выходзіць, прычына неудачы павінна вказываць на адную адпаведальнасць, а не на заплутаны ланцюг задач. Раздзеліце правілы часткавання дадзеных ад правілаў ўзяць іх. Змена адных не павінна вымагаць перапісву іншых, калі зменяюцыся паказателі якосці.
def compute_chunk_hash(text: str) -> str:
return hashlib.md5(text.encode("utf-8")).hexdigest()
def diff_chunks(old_registry: dict, new_chunks: list[str]) -> dict:
new_hash_map = {compute_chunk_hash(c): c for c in new_chunks}
old_hashes = set(old_registry.keys())
new_hashes = set(new_hash_map.keys())
return {
"added": {h: new_hash_map[h] for h in (new_hashes - old_hashes)},
"removed": {h: old_registry[h] for h in (old_hashes - new_hashes)},
"unchanged": {h: old_registry[h] for h in (old_hashes & new_hashes)},
}
v1 → v2 CDC result:
✅ Unchanged : 8 (kept — zero re-embedding cost)
➕ Added : 6 (embedded + inserted)
➖ Removed : 4 (deleted from ChromaDB)
💰 API calls saved: 8/14 (57% reuse)
v2 → v3 CDC result:
✅ Unchanged : 10 (kept - zero re-embedding cost)
➕ Added : 4 (embedded + inserted)
➖ Removed : 2 (deleted from ChromaDB)
💰 API calls saved: 10/14 (71% reuse)
Выбіранне дадзеных на аднойчынку з урахоўванням свежасці (Cell 14C)
Этап 14C з’явоўкі дадзеных за прыоритэтам свежасці працюе найкраща, калі яго розглядаць як вимерную паверхню. Зафіксавайце адна ідеальная транскрыпцыя, адин прыклад неудачы і запіс пра відкатанне роботы, перш чым расширваць масштабы. Разглядзайце этап як кантракт між вхіднымі дадзенымі та паверыжанымі выходнымі рэзультатамі. Паказвайце назвы артыфактаў, задаюце критэрыя успеху та адмовляйцеся ад безсловеснага частковага завершэння роботы. Раздзеляйце правілы часткавага разбівання дадзеных і правілы ўзяць іх з памяці. Змена адных не должна прымусваць перапісванне іншых, калі змянююцыся паказнікі якасці.
def recency_decay(ingested_at_str: str, half_life_days: float = 30) -> float:
ingested = datetime.fromisoformat(ingested_at_str)
days_gone = (datetime.now() - ingested).total_seconds() / 86400
λ = math.log(2) / half_life_days
return round(math.exp(-λ * days_gone), 4)
blended = alpha * cosine_score + (1 - alpha) * recency_score
# Default: 0.85 * cosine + 0.15 * recency
Частка 5 — Тэставанне з PDF-файламі з калькамі
Тэставанне часткі 5 з атраментамі работае наяўней, калі яго спрыяваць як мерыемую паверхню. Зберагуце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перад расшырэнням масштаба. Запісвайце часы выканання і косты токеноў або запытак па боку ад функцыйнальных рэзультатаў. Візуабельнасць костаў з самага пачатку запобегае неспакойным рахункам, калі процес пераходзіць з дэмовай среды ў спяльныя сераўеры. Раздзеліце політыку частковага обробкі дадзеных ад політыки ўзяць іх. Змена адной з яных не должна прымусваць перапісванне другой, калі зменяюцыся паказнікі якосці. Тэставанне часткі 5 з атраментамі работае наяўней, калі яго спрыяваць як мерыемую паверхню. Зберагуце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перад расшырэнням масштаба. Дакументавайце як успішны, так і вярнучыся шляхы. Перапрыбуткі, людзкія контрольныя пункты і обробка некоректных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней.
TEST 1: Full ingest of v1
TEST 2: Staleness check — same file, correctly skipped
TEST 3: Baseline queries against v1
TEST 4: Copy v2 over active file → CDC kicks in
TEST 5: Same queries now return v2 content, newer chunks visible in recency scores
TEST 6: Copy v3 over active file → second CDC cycle
TEST 7: Recency verification — v3 chunks score highest across the board
TEST 8: Full stack test — weighted retrieval + conversation memory combined
Рэзультаты і паўнастаішчаныя адпаведзі
У стадії Рэзультатаў і парадактаваных адказоў неабходна перад змянай коду вызначыць інпуты, адпаведальную особу за крок і крэтыры завершэння. Аперацыяныя працавнікі должны магчымае перайсці на гэты крок з вядомага пункта контролю, не спрабоўваючы здагадвацца пра схованы стан. Лепш выбіраць маленькія, тэставаныя елементы замест большых скрыптаў. Калі крок не выйшоў, прычына неудачы должна вказываць на адзін конкрэтны аспект, а не на заплутаны ланцужок задач. Прытамульвайце тыя часткі тексту, якія фактычна лежалі в основе адказа. Без цых цытатаў аперацыяныя працавнікі не зможуць адразніць галюцинацыю ад працягу ў індэксаванні.
Падсумак эфектыўнасці
Для стадіі падчытання эфектыўнасці неабходна перад змянай коду задаць вхідныя даны, адпаведальнага за крок і крэтырыя завершэння. Аперацыёныя працавнікі должны магчымае запускаць крок з вядомай точкі контролю, не падозрываючы прыхованы стан. Спрыяць гэтай стадіі як даговору межа вхіднымі данымі і падтверджанымі выходнымі рэзультатамі. Даць назвы артыфактам, задаць пераканальнікі успеху і адмовіцца ад беззвучнага частковага завершэння. Цітаваць тыя часткі, якія фактычна лежалі в основе адпаведнай адказы. Без цітатаў аперацыёныя працавнікі не можуць адразніць галюцинацыю ад прасоў у індэксаванні.
Вядомыя абмежэнні
У стадії «Вядомыя лімітаванні» неабходна дэфініцыя вхідных дадзеных, адпаведнага адпаведальніка за крок і крэтарыяў выходу пры перадзеіснаванні коду. Аператары должны магчымае перадзеіснаваць крок з вядомага пункта контролю, не спрабоўваючы здагадвацца пра захаваны стан. Запісвайце час выконання і кост токенаў або запытаў разам з функцыйнальнымі рэзултатамі. Відразы костаў з самага пачатку запобегае неспакойным рахункам, калі процес пераходзіць з дэмаверсіі ў спяльныя среды. Указвайце тыя часткі тексту, якія фактычна лежалі в основе адпаведзьбы. Без цых цитатаў аператары не можуць разлічыць галюцинацію ад прасоў у індэксаванні. У стадії «Вядомыя лімітаванні» неабходна дэфініцыя вхідных дадзеных, адпаведнага адпаведальніка за крок і крэтарыяў выходу пры перадзеіснаванні коду. Аператары должны магчымае перадзеіснаваць крок з вядомага пункта контролю, не спрабоўваючы здагадвацца пра захаваны стан. Дакументавайце як «шчаслівы» шлях, так і шлях вяснавання проблем. Перапрыбуткі, людзкія контралі і обработка некоректных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней.
Што вы створылі
Калі працуеце на стадыі «Што вы створылі», спачатку запісайце умовы: неабяжлівыя данні, сигнал успеху і тое, што выканаецца у разе частковага нявыполнення. Такі список контроля дапамагае заліцварыць пазнейшыя змены ў кодзе. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшоў, прычына нявыполнення павінна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцужок задач. Перад налаштаваннем запитоў пераканайцеся, наскількі эфектыва система адпаведзядае на фіксаваны набор запитаў. Частыя змены запитоў рэдка калі вядуць да павышэння якосці адпаведзенняў.
PDF on disk
└► SHA256 hash check (staleness)
├► Unchanged → skip
└► Changed → CDC diff
├► Unchanged chunks → kept in ChromaDB (zero API cost)
├► Removed chunks → deleted from ChromaDB
└► Added chunks → embed (Gemini) → store (ChromaDB)
↓
User question
└► embed_query() [RETRIEVAL_QUERY task type]
└► ChromaDB cosine search (TOP_K × 3 candidates)
└► recency_decay() per chunk
└► blended score re-ranking
└► top-5 chunks as context
└► ConversationMemory.get_messages_with_history()
└► gpt-oss-20b via Groq/HuggingFace
└► grounded answer + checkpoint to disk
Чэк-ліст для эксплуатацыі
Стадыя чэк-ліста для эксплуатацыі будзе эфектыва, якшо ёй ставіцца задача стварыць меркаваную базу дадзеных. Запісайце адны ідеальны прыклад роботы, адзін прыклад нявыполнення і прыметкі па адкату перш чым расширваце сферу працы.
Зберагаюце канфігурацыю праза ў кодзе прыемлікага програмнага забезпечэння. Файлы сяродавішча, храненні секрэтных дадзенаў і флагі функцыйяй должны знаходзіцца ў аднам месцы, куды аператары можаюць адбавіць аудыт без неабяжнага чытання всей структуры.
Раздзеляйце політыку часткавання дадзенаў ад політыки ўзяць іх. Змена адной з яных не должна прымусваць перапісванне другой, калі зменяюцыся паказнікі якосці.
Калі дозволяе бюджет, адбавяйце тэст на працэсанне критычнага маршруту ў системе CI з викорыстанням фіксатываў, а не рэальных платных API.
Документавайце як шлях успеху, так і шлях вяснавання проблем. Перапрыбуткі, людзкія контрольныя пункты і обработка непрацюючых паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней.
Раздзеляйце політыку часткавання дадзенаў ад політыки ўзяць іх. Змена адной з яых не должна прымусваць перапісванне другой, калі зменяюцыся паказнікі якосці.
Перш чым запускать даную структуру, заморозьце версіі, зафіксавце «золаты» транскрыпты для критичных етапаў і паказвце способы вярнення да пачатковага стану. У спільных середавішчах неабходны ліміты частоты запуска, пераканання ў належнасці тэриторыі і чысткі власнік для змены секретных даных. Валіце надзейнасць працы над красавімі разовымі дэманстрацыямі.
Прыметкі для 8d172e929623: не кладзіце ключы прадаўцаў у репазітарый, задаце верхнюю межу токенав для кожной сесіі і зберагачыце транскрыпты празаўседы ў фіксатырах ацэнкі, каб пазнейшыя замены моделяў заставаліся пораўнанымі.