Практичні нотатки: Граф RAG у дії: чому стандартний RAG не справляється з складними запитами
Покрокове пояснення до практичних нотаток: Graph RAG в дії: чому стандартний RAG не справляється з складними запитами: контракти, перевірки та готові блоки коду для команд, які використовують цю схему.
Використовуйте цей документ як оновлену версію ідей з книги „Graph RAG in Action: Why Standard RAG Fails at Complex Queries (And How Graph RAG Fixes It)“ для співробітників-операторів: чіткі етапи, впорядковані блоки коду та примітки щодо відновлення, які залишаються при передачі обов’язків. Етап Огляду найкраще функціонує, якщо його розглядати як вимірювану основу. Збережіть один ідеальний запис, один випадок збою та примітки щодо скасування змін перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій.
Справжня проблема: роз’єднані фрагменти
Для справжньої стадії роз’єднання необхідно визначити вхідні дані, власника кроку та критерії завершення ще до змін у коді. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цю стадію як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового завершення. Наводьте конкретні уривки, які лежать в основі відповіді. Без посилань оператори не зможуть відрізнити галюцинації від проблем із індексуванням.
Що робить Graph RAG по-іншому
Для етапу What Graph RAG, який займається обробкою даних, необхідно визначити вхідні дані, відповідальну особу за кожен крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись визначити прихований стан системи. Необхідно фіксувати час виконання та витрати на токени чи запити поруч із функціональними результатами. Чітке відображення витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні середовища. Необхідно наводити конкретні уривки тексту, на яких ґрунтується відповідь. Без посилань оператори не можуть відрізнити галюцинації від проблем із індексуванням.
Feature | Vector RAG | Graph RAG
-------------------|---------------------|-------------------------
Storage unit | Text chunks | Entities + relationships
Retrieval method | Semantic similarity | Graph traversal
Best for | Direct lookup | Multi-hop reasoning
Context scope | Local fragment | Connected network
Вузьке місце у вилученні даних
На етапі «Вузьке місе витягування» необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Конфігурацію слід тримати окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевірити, не читаючи весь код. Наводьте уривки тексту, які фактично лежать в основі відповіді. Без посилань оператори не зможуть відрізнити галюцинацію від проблем із індексуванням. На етапі «Вузьке місе витягування» необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану структуру.
пайплайн.Як працює пайплайн Graph RAG
Під час роботи над етапом «Як працює Graph RAG» спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність у подальших змінах коду. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Придумайте назви для кожного елемента, визначте критерії успіху та не допускайте беззвучного часткового виконання завдань. Вимірюйте рівень відтворення інформації на фіксованому наборі запитань перед налаштуванням підказок. Часта зміна підказок рідко вирішує проблеми слабкого пошуку інформації.
flowchart LR
Q[User query] --> E[Entity extraction]
E --> G[Graph construction]
G --> T[Traversal + path ranking]
T --> C[Path context]
C --> L[LLM answer generation]
L --> R[Final response]
План реалізації (POC)
Під час роботи над етапом POC «Креслення імплементації» спочатку запишіть умови використання: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-версії до спільних середовищ. Вимірюйте рівень точності відповідей на фіксований набір запитань перед налаштуванням промптів. Часта зміна промптів рідко допомагає покращити якість отримання інформації.
1. Витягування структурованих фактів
Під час виконання етапу 1 «Витягнення структурованих фактів» спочатку запишіть умови роботи: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код. Вимірюйте рівень відтворення інформації за фіксованим набором запитань перед налаштуванням підказок. Зміна підказок рідко вирішує проблеми слабкого пошуку інформації. Під час виконання етапу 1 «Витягнення структурованих фактів» спочатку запишіть умови роботи: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Віддавайте перевагу невеликим, тестованим одиницям коду перед об’ємними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій.
import networkx as nx
SAMPLE_TRIPLES = [
("John Doe", "is CEO of", "Acme Corp"),
("Jane Smith", "sits on board of", "Acme Corp"),
("Jane Smith", "mentors", "John Doe"),
]
def build_graph(triples):
graph = nx.DiGraph()
for source, relation, target in triples:
graph.add_node(source)
graph.add_node(target)
graph.add_edge(source, target, relation=relation)
return graph
2. Знаходження кандидатських шляхів
Етап 2 «Знаходження кандидатських шляхів» працює найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як угоду між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Розділіть політику часткового оброблення даних від політики їх пошуку. Зміна однієї з них не повинна змушувати переписувати іншу при зміні показників якості.
def traverse_graph(graph, seeds, depth=2):
paths = []
seen = set()
undirected = graph.to_undirected()
for seed in seeds:
for target in graph.nodes:
if seed == target:
continue
for path in nx.all_simple_paths(undirected, source=seed, target=target, cutoff=depth):
canonical = tuple(path) if tuple(path) <= tuple(reversed(path)) else tuple(reversed(path))
if canonical in seen:
continue
seen.add(canonical)
paths.append(path)
return paths
3. Оцінка шляхів
Етап оцінки 3 шляхів працює найкраще, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний приклад, один випадок невдачі та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуальний контроль витрат заздалегідь запобігає несподіваним рахункам, коли шлях переходить від демо-середовища до спільних середовищ. Розділяйте політику часткової обробки даних та політику їх пошуку. Зміна однієї з них не повинна змушувати переписувати іншу при зміні показників якості.
def score_path(graph, path, query):
query_tokens = set(tokenize(query))
path_nodes = [node.lower() for node in path]
path_rels = []
for i in range(len(path) - 1):
rel, _ = get_edge_relation(graph, path[i], path[i + 1])
path_rels.append(rel.lower())
path_text = " ".join(path_nodes + path_rels)
overlap_score = len(query_tokens.intersection(set(tokenize(path_text)))) * 10
node_score = sum(1 for node in path_nodes if any(token in node for token in query_tokens)) * 5
rel_score = sum(1 for rel in path_rels if any(token in rel for token in query_tokens)) * 8
length_penalty = max(0, len(path) - 2) * 2
connection_bonus = sum(len(node.split()) for node in path_nodes)
return overlap_score + node_score + rel_score + connection_bonus - length_penalty
4. Перетворіть найкращий шлях у контекст
Найкраща стадія процесу „4 Convert“ функціонує найефективніше, коли її розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код. Розділяйте політику часткової обробки даних та політику їх отримання. Зміна однієї з них не повинна змушувати переписувати іншу, коли змінюються показники якості. Найкраща стадія процесу „4 Convert“ функціонує найефективніше, коли її розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям коду перед складними скриптами. Коли якась крок виконання зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій.
def path_to_text(graph, path):
lines = []
for i in range(len(path) - 1):
source = path[i]
target = path[i + 1]
relation, reversed_edge = get_edge_relation(graph, source, target)
if reversed_edge:
lines.append(f"{target} {relation} {source}.")
else:
lines.append(f"{source} {relation} {target}.")
return " ".join(lines)
5. Задайте запит LLM за обраним шляхом
На етапі 5 «Запитайте у LLM» необхідно визначити вхідні дані, відповідальну особу за виконання кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте безповідомного часткового завершення. У разі, коли наступним кроком є код або виклик інструменту, віддавайте перевагу структурованим результатам із перевіркою схеми перед вільним текстовим форматом.
def generate_llm_answer(query, context):
prompt = (
"You are a helpful assistant. Use only the graph facts below to answer the query clearly. "
"Do not introduce any new information. "
f"If the answer is not directly supported by these facts, say you don't know.\n\n"
f"Question: {query}\n\n"
"Graph facts:\n"
f"{context}\n\n"
"Answer with a short explanation of the supporting facts:"
)
response = client.responses.create(
model=config["deployment_name"],
input=prompt,
max_output_tokens=250,
temperature=0.1,
)
return response.output_text.strip()
6. Зробіть його доступним як демо-API
Для проекту 6 Expose як етапу необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись визначити прихований стан. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-середовища до спільних. Наводьте уривки тексту, які фактично лягли в основу відповіді. Без посилань оператори не зможуть відрізнити галюцинації від проблем з індексуванням.
@app.post("/query")
def query_graph_rag(request: QueryRequest):
query = request.query.strip()
graph = build_graph(SAMPLE_TRIPLES)
answer, path, context, ranked_paths = answer_query(query, graph)
return {
"query": query,
"answer": answer,
"reasoning_path": context,
"path_nodes": path,
"ranked_paths": ranked_paths,
}
Перехід від прототипу до продакшну: масштабування
Щоб перейти від прототипу до стадії продакшну, необхідно визначити вхідні дані, відповідальну особу за кожен етап та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати етап з відомої точки контролю, не намагаючись вгадати прихований стан. Конфігурацію слід тримати окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевірити, не читаючи весь код. Необхідно наводити конкретні уривки тексту, які лежать в основі відповіді. Без посилань оператори не зможуть відрізнити галюцинації від проблем з індексуванням. Щоб перейти від прототипу до стадії продакшну, необхідно визначити вхідні дані, відповідальну особу за кожен етап та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати етап з відомої точки контролю, не намагаючись вгадати прихований стан. Краще використовувати невеликі, перевірювані одиниці коду замість об’ємних скриптів. Коли етап зазнає невдачі, причина має вказувати на конкретну відповідальність.
ніж заплутана система трубопроводів.1. Система автоматичної екстракції (справжній вузький місце)
Під час роботи над етапом 1 «Автоматична екстракція» спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви елементам, визначте критерії успіху та не допускайте беззвучного часткового виконання. Вимірюйте рівень відтворення інформації на фіксованому наборі запитань перед налаштуванням запрошень. Часті зміни запрошень рідко вирішують проблеми слабкої системи пошуку.
2. Постійне зберігання корпоративної графи
Під час роботи над другим етапом Persistent Enterprise Graph спочатку запишіть умови використання: необхідні параметри вхідних даних, сигнал про успішну обробку та наслідки часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Запишіть час виконання та витрати на токени або запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-середовища до спільних. Вимірюйте рівень точності відповідей на фіксований набір запитань перед налаштуванням формулювань запитів. Часта зміна формулювань рідко допомагає покращити якість пошуку.
3. Оптимізоване пошукове функціонування та керування затримками
Під час роботи над третім етапом «Оптимізація затримки отримання даних» спочатку запишіть умови взаємодії: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код. Вимірюйте рівень відтворення інформації на фіксованому наборі запитань перед налаштуванням підказок. Зміни підказок рідко вирішують проблеми слабкої системи пошуку. Під час роботи над третім етапом «Оптимізація затримки отримання даних» спочатку запишіть умови взаємодії: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Віддавайте перевагу малим, тестованим одиницям коду перед великими скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну функцію, а не на складну послідовність операцій.
4. Операціоналізація та безпека
Етап безпеки операціоналізації працює найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань. Розділіть політику часткової обробки даних від політики їх отримання. Зміна однієї з них не повинна змушувати переписувати іншу при зміні показників якості.
Архітектура узагальнення
Етап архітектури підсумку працює найкраще, якщо його розглядати як вимірювану характеристику. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуальний контроль витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-середовища до спільних середовищ. Розділяйте політику часткового оброблення даних від політики їх пошуку. Зміна однієї з них не повинна змушувати переписувати іншу при зміні показників якості.
Дизайн системи POC у короткому огляді
Дизайн системи POC на цьому етапі найкраще функціонує, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код. Розділіть політику часткового оброблення даних від політики їх отримання. Зміна однієї з них не повинна змушувати переписувати іншу, коли змінюються показники якості. Дизайн системи POC на цьому етапі найкраще функціонує, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу малим, тестованим одиницям перед величезними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій.
Результати
На етапі отримання результатів необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви документів, визначте критерії успіху та не допускайте мовчазного часткового завершення роботи. Наводьте уривки тексту, які фактично лягли в основу відповіді. Без посилань оператори не зможуть відрізнити галюцинації від проблем із індексуванням.
Коли використовувати vector RAG проти Graph RAG
Для етапу «Коли використовувати вектори» необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись визначити прихований стан. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Чітке відображення витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні. Наводьте конкретні уривки тексту, які лягли в основу відповіді. Без посилань оператори не зможуть відрізнити галюцинації від проблем з індексуванням.
Чому це важливо
На етапі „Чому це важливо“ необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Конфігурацію слід тримати окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь алгоритм. Наводьте уривки тексту, які фактично лежать в основі відповіді. Без посилань оператори не зможуть відрізнити галюцинацію від проблем із індексуванням. На етапі „Чому це важливо“ необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Віддавайте перевагу невеликим, тестованим одиницям перед об’ємними скриптами. Коли крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність операцій.
Ресурси
Під час роботи на етапі Ресурсів спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Придумайте назви елементів, визначте критерії успіху та не допускайте беззвучного часткового виконання завдань. Перед налаштуванням запитів вимірюйте рівень запам’ятовування на фіксованому наборі запитань. Часта зміна формулювань запитів рідко виправляє проблеми з низькою ефективністю пошуку.
Яка ваша думка?
Під час роботи над етапом «Яка ваша думка?» спочатку запишіть умови використання: необхідні дані вхіду, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді.
Перелік операційних кроків
Під час роботи над етапом переліку операційних кроків спочатку запишіть умови використання: необхідні дані вхіду, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді.
Одночасно задокументуйте оптимальний та резервний сценарії роботи. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки.
Вимірюйте рівень відтворення інформації на фіксованому наборі запитань перед налаштуванням підказок. Часта зміна підказок рідко виправляє проблеми слабкого пошуку інформації.
Фіксуйте версії залежностей та записуйте резюме зображення, яке використовувалося під час демонстрації. Відтворюваність результатів краща за інтуїтивне розуміння.
Віддавайте перевагу невеликим, тестованим одиницям коду перед складними скриптами. Якщо якийсь крок зазнає невдачі, проблема має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.
Вимірюйте рівень відтворення інформації на фіксованому наборі запитань перед налаштуванням підказок. Часта зміна підказок рідко виправляє проблеми слабкого пошуку інформації.
Перед тим, як впроваджувати нові компоненти, заморожуйте версії, створюйте остаточну запись кроків для критичних процесів та перевіряйте кроки скасування змін. У спільних середовищах необхідні обмеження на частоту використання, перевірки прав доступу та чіткий власник для обробки конфіденційних даних. Віддавайте перевагу надійності перед креативними, але одноразовими демонстраціями.
Примітка до пакету 8e81aec03ffd: не включайте ключі постачальника до репозиторію, встановіть ліміт токенів на сеанс та зберігайте транскрипції поруч із фіксами для оцінки, щоб подальша заміна моделей залишалася порівнянною.