mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-04-29 18:36:22 +02:00
Feat: TrustGraph i18n & Documentation Translation Updates (#781)
Native CLI i18n: The TrustGraph CLI has built-in translation support that dynamically loads language strings. You can test and use different languages by simply passing the --lang flag (e.g., --lang es for Spanish, --lang ru for Russian) or by configuring your environment's LANG variable. Automated Docs Translations: This PR introduces autonomously translated Markdown documentation into several target languages, including Spanish, Swahili, Portuguese, Turkish, Hindi, Hebrew, Arabic, Simplified Chinese, and Russian.
This commit is contained in:
parent
19f73e4cdc
commit
f95fd4f052
560 changed files with 236300 additions and 99 deletions
135
docs/tech-specs/__TEMPLATE.ar.md
Normal file
135
docs/tech-specs/__TEMPLATE.ar.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
layout: default
|
||||
title: "المواصفات الفنية لتحميل المعرفة من سطر الأوامر"
|
||||
parent: "Arabic (Beta)"
|
||||
---
|
||||
|
||||
# المواصفات الفنية لتحميل المعرفة من سطر الأوامر
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
تصف هذه المواصفة واجهات سطر الأوامر لتحميل المعرفة إلى TrustGraph، مما يمكّن المستخدمين من استيراد البيانات من مصادر مختلفة من خلال أدوات سطر الأوامر. تدعم هذه التكامل أربع حالات استخدام رئيسية:
|
||||
|
||||
1. **[حالة الاستخدام 1]**: [الوصف]
|
||||
2. **[حالة الاستخدام 2]**: [الوصف]
|
||||
3. **[حالة الاستخدام 3]**: [الوصف]
|
||||
4. **[حالة الاستخدام 4]**: [الوصف]
|
||||
|
||||
## الأهداف
|
||||
|
||||
- **[الهدف 1]**: [الوصف]
|
||||
- **[الهدف 2]**: [الوصف]
|
||||
- **[الهدف 3]**: [الوصف]
|
||||
- **[الهدف 4]**: [الوصف]
|
||||
- **[الهدف 5]**: [الوصف]
|
||||
- **[الهدف 6]**: [الوصف]
|
||||
- **[الهدف 7]**: [الوصف]
|
||||
- **[الهدف 8]**: [الوصف]
|
||||
|
||||
## الخلفية
|
||||
|
||||
[صف الحالة الحالية والقيود التي تعالجها هذه المواصفة]
|
||||
|
||||
تشمل القيود الحالية:
|
||||
- [القيد 1]
|
||||
- [القيد 2]
|
||||
- [القيد 3]
|
||||
- [القيد 4]
|
||||
|
||||
تعالج هذه المواصفة هذه الثغرات من خلال [الوصف]. من خلال [القدرة]، يمكن لـ TrustGraph:
|
||||
- [الفائدة 1]
|
||||
- [الفائدة 2]
|
||||
- [الفائدة 3]
|
||||
- [الفائدة 4]
|
||||
|
||||
## التصميم الفني
|
||||
|
||||
### البنية
|
||||
|
||||
يتطلب تحميل المعرفة من سطر الأوامر المكونات الفنية التالية:
|
||||
|
||||
1. **[المكون 1]**
|
||||
- [وصف وظيفة المكون]
|
||||
- [الميزات الرئيسية]
|
||||
- [نقاط التكامل]
|
||||
|
||||
الوحدة: [مسار-الوحدة]
|
||||
|
||||
2. **[المكون 2]**
|
||||
- [وصف وظيفة المكون]
|
||||
- [الميزات الرئيسية]
|
||||
- [نقاط التكامل]
|
||||
|
||||
الوحدة: [مسار-الوحدة]
|
||||
|
||||
3. **[المكون 3]**
|
||||
- [وصف وظيفة المكون]
|
||||
- [الميزات الرئيسية]
|
||||
- [نقاط التكامل]
|
||||
|
||||
الوحدة: [مسار-الوحدة]
|
||||
|
||||
### نماذج البيانات
|
||||
|
||||
#### [نموذج البيانات 1]
|
||||
|
||||
[وصف نموذج البيانات والبنية]
|
||||
|
||||
مثال:
|
||||
```
|
||||
[Example data structure]
|
||||
```
|
||||
|
||||
هذا النهج يسمح بما يلي:
|
||||
- [الفائدة 1]
|
||||
- [الفائدة 2]
|
||||
- [الفائدة 3]
|
||||
- [الفائدة 4]
|
||||
|
||||
### واجهات برمجة التطبيقات (APIs)
|
||||
|
||||
واجهات برمجة تطبيقات جديدة:
|
||||
- [وصف واجهة برمجة التطبيقات 1]
|
||||
- [وصف واجهة برمجة التطبيقات 2]
|
||||
- [وصف واجهة برمجة التطبيقات 3]
|
||||
|
||||
واجهات برمجة تطبيقات مُعدَّلة:
|
||||
- [واجهة برمجة تطبيقات مُعدَّلة 1] - [وصف التغييرات]
|
||||
- [واجهة برمجة تطبيقات مُعدَّلة 2] - [وصف التغييرات]
|
||||
|
||||
### تفاصيل التنفيذ
|
||||
|
||||
[نهج التنفيذ والاصطلاحات]
|
||||
|
||||
[ملاحظات إضافية حول التنفيذ]
|
||||
|
||||
## اعتبارات الأمان
|
||||
|
||||
[اعتبارات الأمان الخاصة بهذا التنفيذ]
|
||||
|
||||
## اعتبارات الأداء
|
||||
|
||||
[اعتبارات الأداء والاختناقات المحتملة]
|
||||
|
||||
## استراتيجية الاختبار
|
||||
|
||||
[نهج واستراتيجية الاختبار]
|
||||
|
||||
## خطة الترحيل
|
||||
|
||||
[استراتيجية الترحيل إذا كانت قابلة للتطبيق]
|
||||
|
||||
## الجدول الزمني
|
||||
|
||||
[معلومات حول الجدول الزمني إذا تم تحديدها]
|
||||
|
||||
## أسئلة مفتوحة
|
||||
|
||||
- [سؤال مفتوح 1]
|
||||
- [سؤال مفتوح 2]
|
||||
|
||||
## المراجع
|
||||
|
||||
[المراجع إذا كانت قابلة للتطبيق]
|
||||
135
docs/tech-specs/__TEMPLATE.es.md
Normal file
135
docs/tech-specs/__TEMPLATE.es.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificación Técnica de Carga de Conocimiento desde la Línea de Comandos"
|
||||
parent: "Spanish (Beta)"
|
||||
---
|
||||
|
||||
# Especificación Técnica de Carga de Conocimiento desde la Línea de Comandos
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Resumen
|
||||
|
||||
Esta especificación describe las interfaces de línea de comandos para cargar conocimiento en TrustGraph, permitiendo a los usuarios importar datos de diversas fuentes a través de herramientas de línea de comandos. La integración admite cuatro casos de uso principales:
|
||||
|
||||
1. **[Caso de Uso 1]**: [Descripción]
|
||||
2. **[Caso de Uso 2]**: [Descripción]
|
||||
3. **[Caso de Uso 3]**: [Descripción]
|
||||
4. **[Caso de Uso 4]**: [Descripción]
|
||||
|
||||
## Objetivos
|
||||
|
||||
- **[Objetivo 1]**: [Descripción]
|
||||
- **[Objetivo 2]**: [Descripción]
|
||||
- **[Objetivo 3]**: [Descripción]
|
||||
- **[Objetivo 4]**: [Descripción]
|
||||
- **[Objetivo 5]**: [Descripción]
|
||||
- **[Objetivo 6]**: [Descripción]
|
||||
- **[Objetivo 7]**: [Descripción]
|
||||
- **[Objetivo 8]**: [Descripción]
|
||||
|
||||
## Antecedentes
|
||||
|
||||
[Describa el estado actual y las limitaciones que esta especificación aborda]
|
||||
|
||||
Las limitaciones actuales incluyen:
|
||||
- [Limitación 1]
|
||||
- [Limitación 2]
|
||||
- [Limitación 3]
|
||||
- [Limitación 4]
|
||||
|
||||
Esta especificación aborda estas deficiencias mediante [descripción]. Al [capacidad], TrustGraph puede:
|
||||
- [Beneficio 1]
|
||||
- [Beneficio 2]
|
||||
- [Beneficio 3]
|
||||
- [Beneficio 4]
|
||||
|
||||
## Diseño Técnico
|
||||
|
||||
### Arquitectura
|
||||
|
||||
La carga de conocimiento desde la línea de comandos requiere los siguientes componentes técnicos:
|
||||
|
||||
1. **[Componente 1]**
|
||||
- [Descripción de la funcionalidad del componente]
|
||||
- [Características clave]
|
||||
- [Puntos de integración]
|
||||
|
||||
Módulo: [module-path]
|
||||
|
||||
2. **[Componente 2]**
|
||||
- [Descripción de la funcionalidad del componente]
|
||||
- [Características clave]
|
||||
- [Puntos de integración]
|
||||
|
||||
Módulo: [module-path]
|
||||
|
||||
3. **[Componente 3]**
|
||||
- [Descripción de la funcionalidad del componente]
|
||||
- [Características clave]
|
||||
- [Puntos de integración]
|
||||
|
||||
Módulo: [module-path]
|
||||
|
||||
### Modelos de Datos
|
||||
|
||||
#### [Modelo de Datos 1]
|
||||
|
||||
[Descripción del modelo de datos y su estructura]
|
||||
|
||||
Ejemplo:
|
||||
```
|
||||
[Example data structure]
|
||||
```
|
||||
|
||||
Este enfoque permite:
|
||||
- [Beneficio 1]
|
||||
- [Beneficio 2]
|
||||
- [Beneficio 3]
|
||||
- [Beneficio 4]
|
||||
|
||||
### APIs
|
||||
|
||||
Nuevas APIs:
|
||||
- [Descripción de la API 1]
|
||||
- [Descripción de la API 2]
|
||||
- [Descripción de la API 3]
|
||||
|
||||
APIs modificadas:
|
||||
- [API modificada 1] - [Descripción de los cambios]
|
||||
- [API modificada 2] - [Descripción de los cambios]
|
||||
|
||||
### Detalles de implementación
|
||||
|
||||
[Enfoque y convenciones de implementación]
|
||||
|
||||
[Notas adicionales de implementación]
|
||||
|
||||
## Consideraciones de seguridad
|
||||
|
||||
[Consideraciones de seguridad específicas de esta implementación]
|
||||
|
||||
## Consideraciones de rendimiento
|
||||
|
||||
[Consideraciones de rendimiento y posibles cuellos de botella]
|
||||
|
||||
## Estrategia de pruebas
|
||||
|
||||
[Enfoque y estrategia de pruebas]
|
||||
|
||||
## Plan de migración
|
||||
|
||||
[Estrategia de migración si es aplicable]
|
||||
|
||||
## Cronograma
|
||||
|
||||
[Información del cronograma si se especifica]
|
||||
|
||||
## Preguntas abiertas
|
||||
|
||||
- [Pregunta abierta 1]
|
||||
- [Pregunta abierta 2]
|
||||
|
||||
## Referencias
|
||||
|
||||
[Referencias si es aplicable]
|
||||
135
docs/tech-specs/__TEMPLATE.he.md
Normal file
135
docs/tech-specs/__TEMPLATE.he.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Command-Line Loading Knowledge Technical Specification"
|
||||
parent: "Hebrew (Beta)"
|
||||
---
|
||||
|
||||
# Command-Line Loading Knowledge Technical Specification
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Overview
|
||||
|
||||
מפרט זה מתאר את ממשקי שורת הפקודה לטעינת ידע לתוך TrustGraph, ומאפשר למשתמשים לקלוט נתונים ממקורות שונים באמצעות כלי שורת פקודה. האינטגרציה תומכת בארבעה תרחישי שימוש עיקריים:
|
||||
|
||||
1. **[Use Case 1]**: [Description]
|
||||
2. **[Use Case 2]**: [Description]
|
||||
3. **[Use Case 3]**: [Description]
|
||||
4. **[Use Case 4]**: [Description]
|
||||
|
||||
## Goals
|
||||
|
||||
- **[Goal 1]**: [Description]
|
||||
- **[Goal 2]**: [Description]
|
||||
- **[Goal 3]**: [Description]
|
||||
- **[Goal 4]**: [Description]
|
||||
- **[Goal 5]**: [Description]
|
||||
- **[Goal 6]**: [Description]
|
||||
- **[Goal 7]**: [Description]
|
||||
- **[Goal 8]**: [Description]
|
||||
|
||||
## Background
|
||||
|
||||
[Describe the current state and limitations that this specification addresses]
|
||||
|
||||
מגבלות נוכחיות כוללות:
|
||||
- [Limitation 1]
|
||||
- [Limitation 2]
|
||||
- [Limitation 3]
|
||||
- [Limitation 4]
|
||||
|
||||
מפרט זה מתייחס לפערים אלה על ידי [description]. באמצעות [capability], TrustGraph יכול:
|
||||
- [Benefit 1]
|
||||
- [Benefit 2]
|
||||
- [Benefit 3]
|
||||
- [Benefit 4]
|
||||
|
||||
## Technical Design
|
||||
|
||||
### Architecture
|
||||
|
||||
טעינת ידע משורת הפקודה דורשת את הרכיבים הטכניים הבאים:
|
||||
|
||||
1. **[Component 1]**
|
||||
- [Description of component functionality]
|
||||
- [Key features]
|
||||
- [Integration points]
|
||||
|
||||
Module: [module-path]
|
||||
|
||||
2. **[Component 2]**
|
||||
- [Description of component functionality]
|
||||
- [Key features]
|
||||
- [Integration points]
|
||||
|
||||
Module: [module-path]
|
||||
|
||||
3. **[Component 3]**
|
||||
- [Description of component functionality]
|
||||
- [Key features]
|
||||
- [Integration points]
|
||||
|
||||
Module: [module-path]
|
||||
|
||||
### Data Models
|
||||
|
||||
#### [Data Model 1]
|
||||
|
||||
[Description of data model and structure]
|
||||
|
||||
Example:
|
||||
```
|
||||
[Example data structure]
|
||||
```
|
||||
|
||||
גישה זו מאפשרת:
|
||||
- [Benefit 1]
|
||||
- [Benefit 2]
|
||||
- [Benefit 3]
|
||||
- [Benefit 4]
|
||||
|
||||
### ממשקי API
|
||||
|
||||
ממשקי API חדשים:
|
||||
- [API description 1]
|
||||
- [API description 2]
|
||||
- [API description 3]
|
||||
|
||||
ממשקי API ששונו:
|
||||
- [Modified API 1] - [Description of changes]
|
||||
- [Modified API 2] - [Description of changes]
|
||||
|
||||
### פרטי יישום
|
||||
|
||||
[גישת יישום ועקרונות]
|
||||
|
||||
[הערות נוספות בנוגע ליישום]
|
||||
|
||||
## שיקולי אבטחה
|
||||
|
||||
[שיקולי אבטחה ספציפיים ליישום זה]
|
||||
|
||||
## שיקולי ביצועים
|
||||
|
||||
[שיקולי ביצועים וצווארי בקבוק פוטנציאליים]
|
||||
|
||||
## אסטרטגיית בדיקות
|
||||
|
||||
[גישת אסטרטגיית בדיקות]
|
||||
|
||||
## תוכנית מעבר
|
||||
|
||||
[אסטרטגיית מעבר, אם רלוונטית]
|
||||
|
||||
## ציר זמן
|
||||
|
||||
[מידע על ציר הזמן, אם מצוין]
|
||||
|
||||
## שאלות פתוחות
|
||||
|
||||
- [Open question 1]
|
||||
- [Open question 2]
|
||||
|
||||
## מקורות
|
||||
|
||||
[מקורות, אם רלוונטיים]
|
||||
135
docs/tech-specs/__TEMPLATE.hi.md
Normal file
135
docs/tech-specs/__TEMPLATE.hi.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
layout: default
|
||||
title: "कमांड-लाइन लोडिंग नॉलेज टेक्निकल स्पेसिफिकेशन"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# कमांड-लाइन लोडिंग नॉलेज टेक्निकल स्पेसिफिकेशन
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## अवलोकन
|
||||
|
||||
यह स्पेसिफिकेशन ट्रस्टग्राफ में नॉलेज लोड करने के लिए कमांड-लाइन इंटरफेस का वर्णन करता है, जो उपयोगकर्ताओं को कमांड-लाइन टूल के माध्यम से विभिन्न स्रोतों से डेटा प्राप्त करने में सक्षम बनाता है। एकीकरण चार प्राथमिक उपयोग मामलों का समर्थन करता है:
|
||||
|
||||
1. **[उपयोग मामला 1]**: [विवरण]
|
||||
2. **[उपयोग मामला 2]**: [विवरण]
|
||||
3. **[उपयोग मामला 3]**: [विवरण]
|
||||
4. **[उपयोग मामला 4]**: [विवरण]
|
||||
|
||||
## लक्ष्य
|
||||
|
||||
- **[लक्ष्य 1]**: [विवरण]
|
||||
- **[लक्ष्य 2]**: [विवरण]
|
||||
- **[लक्ष्य 3]**: [विवरण]
|
||||
- **[लक्ष्य 4]**: [विवरण]
|
||||
- **[लक्ष्य 5]**: [विवरण]
|
||||
- **[लक्ष्य 6]**: [विवरण]
|
||||
- **[लक्ष्य 7]**: [विवरण]
|
||||
- **[लक्ष्य 8]**: [विवरण]
|
||||
|
||||
## पृष्ठभूमि
|
||||
|
||||
[वर्तमान स्थिति और सीमाओं का वर्णन करें जिन्हें यह स्पेसिफिकेशन संबोधित करता है]
|
||||
|
||||
वर्तमान सीमाओं में शामिल हैं:
|
||||
- [सीमा 1]
|
||||
- [सीमा 2]
|
||||
- [सीमा 3]
|
||||
- [सीमा 4]
|
||||
|
||||
यह स्पेसिफिकेशन इन कमियों को [विवरण] द्वारा संबोधित करता है। [क्षमता] के माध्यम से, ट्रस्टग्राफ:
|
||||
- [लाभ 1]
|
||||
- [लाभ 2]
|
||||
- [लाभ 3]
|
||||
- [लाभ 4]
|
||||
|
||||
## तकनीकी डिजाइन
|
||||
|
||||
### आर्किटेक्चर
|
||||
|
||||
कमांड-लाइन नॉलेज लोडिंग के लिए निम्नलिखित तकनीकी घटकों की आवश्यकता होती है:
|
||||
|
||||
1. **[घटक 1]**
|
||||
- [घटक कार्यक्षमता का विवरण]
|
||||
- [मुख्य विशेषताएं]
|
||||
- [एकीकरण बिंदु]
|
||||
|
||||
मॉड्यूल: [मॉड्यूल-पाथ]
|
||||
|
||||
2. **[घटक 2]**
|
||||
- [घटक कार्यक्षमता का विवरण]
|
||||
- [मुख्य विशेषताएं]
|
||||
- [एकीकरण बिंदु]
|
||||
|
||||
मॉड्यूल: [मॉड्यूल-पाथ]
|
||||
|
||||
3. **[घटक 3]**
|
||||
- [घटक कार्यक्षमता का विवरण]
|
||||
- [मुख्य विशेषताएं]
|
||||
- [एकीकरण बिंदु]
|
||||
|
||||
मॉड्यूल: [मॉड्यूल-पाथ]
|
||||
|
||||
### डेटा मॉडल
|
||||
|
||||
#### [डेटा मॉडल 1]
|
||||
|
||||
[डेटा मॉडल और संरचना का विवरण]
|
||||
|
||||
उदाहरण:
|
||||
```
|
||||
[Example data structure]
|
||||
```
|
||||
|
||||
यह दृष्टिकोण निम्नलिखित की अनुमति देता है:
|
||||
- [लाभ 1]
|
||||
- [लाभ 2]
|
||||
- [लाभ 3]
|
||||
- [लाभ 4]
|
||||
|
||||
### एपीआई (APIs)
|
||||
|
||||
नए एपीआई (APIs):
|
||||
- [एपीआई विवरण 1]
|
||||
- [एपीआई विवरण 2]
|
||||
- [एपीआई विवरण 3]
|
||||
|
||||
संशोधित एपीआई (APIs):
|
||||
- [संशोधित एपीआई 1] - [परिवर्तनों का विवरण]
|
||||
- [संशोधित एपीआई 2] - [परिवर्तनों का विवरण]
|
||||
|
||||
### कार्यान्वयन विवरण
|
||||
|
||||
[कार्यान्वयन दृष्टिकोण और परंपराएं]
|
||||
|
||||
[अतिरिक्त कार्यान्वयन नोट्स]
|
||||
|
||||
## सुरक्षा संबंधी विचार
|
||||
|
||||
[इस कार्यान्वयन के लिए विशिष्ट सुरक्षा संबंधी विचार]
|
||||
|
||||
## प्रदर्शन संबंधी विचार
|
||||
|
||||
[प्रदर्शन संबंधी विचार और संभावित बाधाएं]
|
||||
|
||||
## परीक्षण रणनीति
|
||||
|
||||
[परीक्षण दृष्टिकोण और रणनीति]
|
||||
|
||||
## माइग्रेशन योजना
|
||||
|
||||
[यदि लागू हो, तो माइग्रेशन रणनीति]
|
||||
|
||||
## समयरेखा
|
||||
|
||||
[यदि निर्दिष्ट किया गया है, तो समयरेखा जानकारी]
|
||||
|
||||
## अनुत्तरित प्रश्न
|
||||
|
||||
- [अनुत्तरित प्रश्न 1]
|
||||
- [अनुत्तरित प्रश्न 2]
|
||||
|
||||
## संदर्भ
|
||||
|
||||
[यदि लागू हो, तो संदर्भ]
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Command-Line Loading Knowledge Technical Specification"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Command-Line Loading Knowledge Technical Specification
|
||||
|
||||
## Overview
|
||||
|
|
|
|||
135
docs/tech-specs/__TEMPLATE.pt.md
Normal file
135
docs/tech-specs/__TEMPLATE.pt.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificação Técnica de Carregamento de Conhecimento via Linha de Comando"
|
||||
parent: "Portuguese (Beta)"
|
||||
---
|
||||
|
||||
# Especificação Técnica de Carregamento de Conhecimento via Linha de Comando
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Esta especificação descreve as interfaces de linha de comando para carregar conhecimento no TrustGraph, permitindo que os usuários ingiram dados de várias fontes por meio de ferramentas de linha de comando. A integração suporta quatro casos de uso primários:
|
||||
|
||||
1. **[Caso de Uso 1]**: [Descrição]
|
||||
2. **[Caso de Uso 2]**: [Descrição]
|
||||
3. **[Caso de Uso 3]**: [Descrição]
|
||||
4. **[Caso de Uso 4]**: [Descrição]
|
||||
|
||||
## Objetivos
|
||||
|
||||
- **[Objetivo 1]**: [Descrição]
|
||||
- **[Objetivo 2]**: [Descrição]
|
||||
- **[Objetivo 3]**: [Descrição]
|
||||
- **[Objetivo 4]**: [Descrição]
|
||||
- **[Objetivo 5]**: [Descrição]
|
||||
- **[Objetivo 6]**: [Descrição]
|
||||
- **[Objetivo 7]**: [Descrição]
|
||||
- **[Objetivo 8]**: [Descrição]
|
||||
|
||||
## Contexto
|
||||
|
||||
[Descreva o estado atual e as limitações que esta especificação aborda]
|
||||
|
||||
As limitações atuais incluem:
|
||||
- [Limitação 1]
|
||||
- [Limitação 2]
|
||||
- [Limitação 3]
|
||||
- [Limitação 4]
|
||||
|
||||
Esta especificação aborda essas lacunas ao [descrição]. Ao [capacidade], o TrustGraph pode:
|
||||
- [Benefício 1]
|
||||
- [Benefício 2]
|
||||
- [Benefício 3]
|
||||
- [Benefício 4]
|
||||
|
||||
## Design Técnico
|
||||
|
||||
### Arquitetura
|
||||
|
||||
O carregamento de conhecimento via linha de comando requer os seguintes componentes técnicos:
|
||||
|
||||
1. **[Componente 1]**
|
||||
- [Descrição da funcionalidade do componente]
|
||||
- [Características principais]
|
||||
- [Pontos de integração]
|
||||
|
||||
Módulo: [caminho-do-módulo]
|
||||
|
||||
2. **[Componente 2]**
|
||||
- [Descrição da funcionalidade do componente]
|
||||
- [Características principais]
|
||||
- [Pontos de integração]
|
||||
|
||||
Módulo: [caminho-do-módulo]
|
||||
|
||||
3. **[Componente 3]**
|
||||
- [Descrição da funcionalidade do componente]
|
||||
- [Características principais]
|
||||
- [Pontos de integração]
|
||||
|
||||
Módulo: [caminho-do-módulo]
|
||||
|
||||
### Modelos de Dados
|
||||
|
||||
#### [Modelo de Dados 1]
|
||||
|
||||
[Descrição do modelo de dados e estrutura]
|
||||
|
||||
Exemplo:
|
||||
```
|
||||
[Example data structure]
|
||||
```
|
||||
|
||||
Esta abordagem permite:
|
||||
- [Benefício 1]
|
||||
- [Benefício 2]
|
||||
- [Benefício 3]
|
||||
- [Benefício 4]
|
||||
|
||||
### APIs
|
||||
|
||||
Novas APIs:
|
||||
- [Descrição da API 1]
|
||||
- [Descrição da API 2]
|
||||
- [Descrição da API 3]
|
||||
|
||||
APIs modificadas:
|
||||
- [API modificada 1] - [Descrição das alterações]
|
||||
- [API modificada 2] - [Descrição das alterações]
|
||||
|
||||
### Detalhes de implementação
|
||||
|
||||
[Abordagem e convenções de implementação]
|
||||
|
||||
[Notas adicionais de implementação]
|
||||
|
||||
## Considerações de segurança
|
||||
|
||||
[Considerações de segurança específicas para esta implementação]
|
||||
|
||||
## Considerações de desempenho
|
||||
|
||||
[Considerações de desempenho e possíveis gargalos]
|
||||
|
||||
## Estratégia de testes
|
||||
|
||||
[Abordagem e estratégia de testes]
|
||||
|
||||
## Plano de migração
|
||||
|
||||
[Estratégia de migração, se aplicável]
|
||||
|
||||
## Cronograma
|
||||
|
||||
[Informações sobre o cronograma, se especificadas]
|
||||
|
||||
## Perguntas pendentes
|
||||
|
||||
- [Pergunta pendente 1]
|
||||
- [Pergunta pendente 2]
|
||||
|
||||
## Referências
|
||||
|
||||
[Referências, se aplicável]
|
||||
135
docs/tech-specs/__TEMPLATE.ru.md
Normal file
135
docs/tech-specs/__TEMPLATE.ru.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Техническая спецификация загрузки знаний через командную строку"
|
||||
parent: "Russian (Beta)"
|
||||
---
|
||||
|
||||
# Техническая спецификация загрузки знаний через командную строку
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Обзор
|
||||
|
||||
Эта спецификация описывает интерфейсы командной строки для загрузки знаний в TrustGraph, позволяя пользователям загружать данные из различных источников с помощью инструментов командной строки. Интеграция поддерживает четыре основных сценария использования:
|
||||
|
||||
1. **[Сценарий использования 1]**: [Описание]
|
||||
2. **[Сценарий использования 2]**: [Описание]
|
||||
3. **[Сценарий использования 3]**: [Описание]
|
||||
4. **[Сценарий использования 4]**: [Описание]
|
||||
|
||||
## Цели
|
||||
|
||||
- **[Цель 1]**: [Описание]
|
||||
- **[Цель 2]**: [Описание]
|
||||
- **[Цель 3]**: [Описание]
|
||||
- **[Цель 4]**: [Описание]
|
||||
- **[Цель 5]**: [Описание]
|
||||
- **[Цель 6]**: [Описание]
|
||||
- **[Цель 7]**: [Описание]
|
||||
- **[Цель 8]**: [Описание]
|
||||
|
||||
## Предыстория
|
||||
|
||||
[Опишите текущее состояние и ограничения, которые решает эта спецификация]
|
||||
|
||||
Текущие ограничения включают:
|
||||
- [Ограничение 1]
|
||||
- [Ограничение 2]
|
||||
- [Ограничение 3]
|
||||
- [Ограничение 4]
|
||||
|
||||
Эта спецификация устраняет эти недостатки, [описание]. Благодаря [возможности], TrustGraph может:
|
||||
- [Преимущество 1]
|
||||
- [Преимущество 2]
|
||||
- [Преимущество 3]
|
||||
- [Преимущество 4]
|
||||
|
||||
## Технический дизайн
|
||||
|
||||
### Архитектура
|
||||
|
||||
Загрузка знаний через командную строку требует следующих технических компонентов:
|
||||
|
||||
1. **[Компонент 1]**
|
||||
- [Описание функциональности компонента]
|
||||
- [Основные характеристики]
|
||||
- [Точки интеграции]
|
||||
|
||||
Модуль: [путь_к_модулю]
|
||||
|
||||
2. **[Компонент 2]**
|
||||
- [Описание функциональности компонента]
|
||||
- [Основные характеристики]
|
||||
- [Точки интеграции]
|
||||
|
||||
Модуль: [путь_к_модулю]
|
||||
|
||||
3. **[Компонент 3]**
|
||||
- [Описание функциональности компонента]
|
||||
- [Основные характеристики]
|
||||
- [Точки интеграции]
|
||||
|
||||
Модуль: [путь_к_модулю]
|
||||
|
||||
### Модели данных
|
||||
|
||||
#### [Модель данных 1]
|
||||
|
||||
[Описание модели данных и ее структуры]
|
||||
|
||||
Пример:
|
||||
```
|
||||
[Example data structure]
|
||||
```
|
||||
|
||||
Этот подход позволяет:
|
||||
- [Преимущество 1]
|
||||
- [Преимущество 2]
|
||||
- [Преимущество 3]
|
||||
- [Преимущество 4]
|
||||
|
||||
### API
|
||||
|
||||
Новые API:
|
||||
- [Описание API 1]
|
||||
- [Описание API 2]
|
||||
- [Описание API 3]
|
||||
|
||||
Измененные API:
|
||||
- [Измененный API 1] - [Описание изменений]
|
||||
- [Измененный API 2] - [Описание изменений]
|
||||
|
||||
### Детали реализации
|
||||
|
||||
[Подход к реализации и соглашения]
|
||||
|
||||
[Дополнительные примечания по реализации]
|
||||
|
||||
## Вопросы безопасности
|
||||
|
||||
[Вопросы безопасности, специфичные для данной реализации]
|
||||
|
||||
## Вопросы производительности
|
||||
|
||||
[Вопросы производительности и потенциальные узкие места]
|
||||
|
||||
## Стратегия тестирования
|
||||
|
||||
[Подход и стратегия тестирования]
|
||||
|
||||
## План миграции
|
||||
|
||||
[Стратегия миграции, если применимо]
|
||||
|
||||
## Сроки
|
||||
|
||||
[Информация о сроках, если указана]
|
||||
|
||||
## Открытые вопросы
|
||||
|
||||
- [Открытый вопрос 1]
|
||||
- [Открытый вопрос 2]
|
||||
|
||||
## Ссылки
|
||||
|
||||
[Ссылки, если применимо]
|
||||
135
docs/tech-specs/__TEMPLATE.sw.md
Normal file
135
docs/tech-specs/__TEMPLATE.sw.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Vipimo vya Kiufundi vya Kujaza Habari Kupitia Amri ya Kamba"
|
||||
parent: "Swahili (Beta)"
|
||||
---
|
||||
|
||||
# Vipimo vya Kiufundi vya Kujaza Habari Kupitia Amri ya Kamba
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Muhtasari
|
||||
|
||||
Vipimo hivi vinaelezea interface za amri ya kamba kwa ajili ya kujaza habari katika TrustGraph, na kuwezesha watumiaji kusambaza data kutoka vyanzo mbalimbali kupitia zana za amri ya kamba. Uunganishaji huu unaunga mkono matumizi manne makuu:
|
||||
|
||||
1. **[Matumizi ya 1]**: [Maelezo]
|
||||
2. **[Matumizi ya 2]**: [Maelezo]
|
||||
3. **[Matumizi ya 3]**: [Maelezo]
|
||||
4. **[Matumizi ya 4]**: [Maelezo]
|
||||
|
||||
## Lengo
|
||||
|
||||
- **[Lengo la 1]**: [Maelezo]
|
||||
- **[Lengo la 2]**: [Maelezo]
|
||||
- **[Lengo la 3]**: [Maelezo]
|
||||
- **[Lengo la 4]**: [Maelezo]
|
||||
- **[Lengo la 5]**: [Maelezo]
|
||||
- **[Lengo la 6]**: [Maelezo]
|
||||
- **[Lengo la 7]**: [Maelezo]
|
||||
- **[Lengo la 8]**: [Maelezo]
|
||||
|
||||
## Asili
|
||||
|
||||
[Eleza hali ya sasa na vikwazo ambavyo vipimo hivi vinashughulikia]
|
||||
|
||||
Vikwazo vya sasa ni pamoja na:
|
||||
- [Vikwazo 1]
|
||||
- [Vikwazo 2]
|
||||
- [Vikwazo 3]
|
||||
- [Vikwazo 4]
|
||||
|
||||
Vipimo hivi vinashughulikia pengo hizi kwa [maelezo]. Kwa [uwezo], TrustGraph inaweza:
|
||||
- [Faida 1]
|
||||
- [Faida 2]
|
||||
- [Faida 3]
|
||||
- [Faida 4]
|
||||
|
||||
## Muundo wa Kiufundi
|
||||
|
||||
### Usanifu
|
||||
|
||||
Kujaza habari kupitia amri ya kamba inahitaji vipengele vifuatavyo vya kiufundi:
|
||||
|
||||
1. **[Kipengele cha 1]**
|
||||
- [Maelezo ya utendaji wa kipengele]
|
||||
- [Sifa muhimu]
|
||||
- [Maeneo ya kuunganisha]
|
||||
|
||||
Moduli: [njia-ya-moduli]
|
||||
|
||||
2. **[Kipengele cha 2]**
|
||||
- [Maelezo ya utendaji wa kipengele]
|
||||
- [Sifa muhimu]
|
||||
- [Maeneo ya kuunganisha]
|
||||
|
||||
Moduli: [njia-ya-moduli]
|
||||
|
||||
3. **[Kipengele cha 3]**
|
||||
- [Maelezo ya utendaji wa kipengele]
|
||||
- [Sifa muhimu]
|
||||
- [Maeneo ya kuunganisha]
|
||||
|
||||
Moduli: [njia-ya-moduli]
|
||||
|
||||
### Mifano ya Data
|
||||
|
||||
#### [Mifano ya Data 1]
|
||||
|
||||
[Maelezo ya mfano wa data na muundo]
|
||||
|
||||
Mfano:
|
||||
```
|
||||
[Example data structure]
|
||||
```
|
||||
|
||||
Mbinu hii inaruhusu:
|
||||
- [Faida 1]
|
||||
- [Faida 2]
|
||||
- [Faida 3]
|
||||
- [Faida 4]
|
||||
|
||||
### API
|
||||
|
||||
API mpya:
|
||||
- [Maelezo ya API 1]
|
||||
- [Maelezo ya API 2]
|
||||
- [Maelezo ya API 3]
|
||||
|
||||
API zilizobadilishwa:
|
||||
- [API iliyobadilishwa 1] - [Maelezo ya mabadiliko]
|
||||
- [API iliyobadilishwa 2] - [Maelezo ya mabadiliko]
|
||||
|
||||
### Maelezo ya Utendaji
|
||||
|
||||
[Mbinu na miongozo ya utendaji]
|
||||
|
||||
[Maelezo ya ziada ya utendaji]
|
||||
|
||||
## Masuala ya Usalama
|
||||
|
||||
[Masuala ya usalama maalum kwa utendaji huu]
|
||||
|
||||
## Masuala ya Utendaji
|
||||
|
||||
[Masuala ya utendaji na vizuizi vinavyowezekana]
|
||||
|
||||
## Mkakati wa Majaribio
|
||||
|
||||
[Mbinu na mkakati wa majaribio]
|
||||
|
||||
## Mpango wa Uhamisho
|
||||
|
||||
[Mkakati wa uhamisho ikiwa unafaa]
|
||||
|
||||
## Ratiba
|
||||
|
||||
[Habari ya ratiba ikiwa imebainishwa]
|
||||
|
||||
## Maswali Yaliyobaki
|
||||
|
||||
- [Swali lililobaki 1]
|
||||
- [Swali lililobaki 2]
|
||||
|
||||
## Marejeleo
|
||||
|
||||
[Marejeleo ikiwa yanafaa]
|
||||
135
docs/tech-specs/__TEMPLATE.tr.md
Normal file
135
docs/tech-specs/__TEMPLATE.tr.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Komut Satırı ile Bilgi Yükleme Teknik Özellikleri"
|
||||
parent: "Turkish (Beta)"
|
||||
---
|
||||
|
||||
# Komut Satırı ile Bilgi Yükleme Teknik Özellikleri
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Genel Bakış
|
||||
|
||||
Bu teknik özellik, TrustGraph'a bilgi yüklemek için komut satırı arayüzlerini tanımlar ve kullanıcıların komut satırı araçları aracılığıyla çeşitli kaynaklardan veri almasını sağlar. Bu entegrasyon, dört ana kullanım senaryosunu destekler:
|
||||
|
||||
1. **[Kullanım Senaryosu 1]**: [Açıklama]
|
||||
2. **[Kullanım Senaryosu 2]**: [Açıklama]
|
||||
3. **[Kullanım Senaryosu 3]**: [Açıklama]
|
||||
4. **[Kullanım Senaryosu 4]**: [Açıklama]
|
||||
|
||||
## Hedefler
|
||||
|
||||
- **[Hedef 1]**: [Açıklama]
|
||||
- **[Hedef 2]**: [Açıklama]
|
||||
- **[Hedef 3]**: [Açıklama]
|
||||
- **[Hedef 4]**: [Açıklama]
|
||||
- **[Hedef 5]**: [Açıklama]
|
||||
- **[Hedef 6]**: [Açıklama]
|
||||
- **[Hedef 7]**: [Açıklama]
|
||||
- **[Hedef 8]**: [Açıklama]
|
||||
|
||||
## Arka Plan
|
||||
|
||||
[Mevcut durumu ve bu teknik özelliğin ele aldığı sınırlamaları açıklayın]
|
||||
|
||||
Mevcut sınırlamalar şunlardır:
|
||||
- [Sınırlama 1]
|
||||
- [Sınırlama 2]
|
||||
- [Sınırlama 3]
|
||||
- [Sınırlama 4]
|
||||
|
||||
Bu teknik özellik, bu eksiklikleri [açıklama] ile giderir. [Yeteneği] sayesinde, TrustGraph şunları yapabilir:
|
||||
- [Fayda 1]
|
||||
- [Fayda 2]
|
||||
- [Fayda 3]
|
||||
- [Fayda 4]
|
||||
|
||||
## Teknik Tasarım
|
||||
|
||||
### Mimari
|
||||
|
||||
Komut satırı ile bilgi yükleme, aşağıdaki teknik bileşenleri gerektirir:
|
||||
|
||||
1. **[Bileşen 1]**
|
||||
- [Bileşenin işlevselliğinin açıklaması]
|
||||
- [Temel özellikler]
|
||||
- [Entegrasyon noktaları]
|
||||
|
||||
Modül: [modül-yolu]
|
||||
|
||||
2. **[Bileşen 2]**
|
||||
- [Bileşenin işlevselliğinin açıklaması]
|
||||
- [Temel özellikler]
|
||||
- [Entegrasyon noktaları]
|
||||
|
||||
Modül: [modül-yolu]
|
||||
|
||||
3. **[Bileşen 3]**
|
||||
- [Bileşenin işlevselliğinin açıklaması]
|
||||
- [Temel özellikler]
|
||||
- [Entegrasyon noktaları]
|
||||
|
||||
Modül: [modül-yolu]
|
||||
|
||||
### Veri Modelleri
|
||||
|
||||
#### [Veri Modeli 1]
|
||||
|
||||
[Veri modelinin ve yapısının açıklaması]
|
||||
|
||||
Örnek:
|
||||
```
|
||||
[Example data structure]
|
||||
```
|
||||
|
||||
Bu yaklaşım şunları sağlar:
|
||||
- [Fayda 1]
|
||||
- [Fayda 2]
|
||||
- [Fayda 3]
|
||||
- [Fayda 4]
|
||||
|
||||
### API'ler
|
||||
|
||||
Yeni API'ler:
|
||||
- [API açıklaması 1]
|
||||
- [API açıklaması 2]
|
||||
- [API açıklaması 3]
|
||||
|
||||
Değiştirilen API'ler:
|
||||
- [Değiştirilen API 1] - [Değişikliklerin açıklaması]
|
||||
- [Değiştirilen API 2] - [Değişikliklerin açıklaması]
|
||||
|
||||
### Uygulama Detayları
|
||||
|
||||
[Uygulama yaklaşımı ve kurallar]
|
||||
|
||||
[Ek uygulama notları]
|
||||
|
||||
## Güvenlik Hususları
|
||||
|
||||
[Bu uygulamanın özel güvenlik hususları]
|
||||
|
||||
## Performans Hususları
|
||||
|
||||
[Performans hususları ve olası darboğazlar]
|
||||
|
||||
## Test Stratejisi
|
||||
|
||||
[Test yaklaşımı ve stratejisi]
|
||||
|
||||
## Geçiş Planı
|
||||
|
||||
[Gerekliyse geçiş stratejisi]
|
||||
|
||||
## Zaman Çizelgesi
|
||||
|
||||
[Belirtilmişse zaman çizelgesi bilgileri]
|
||||
|
||||
## Açık Sorular
|
||||
|
||||
- [Açık soru 1]
|
||||
- [Açık soru 2]
|
||||
|
||||
## Referanslar
|
||||
|
||||
[Gerekliyse referanslar]
|
||||
135
docs/tech-specs/__TEMPLATE.zh-cn.md
Normal file
135
docs/tech-specs/__TEMPLATE.zh-cn.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
layout: default
|
||||
title: "命令行加载知识的技术规范"
|
||||
parent: "Chinese (Beta)"
|
||||
---
|
||||
|
||||
# 命令行加载知识的技术规范
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## 概述
|
||||
|
||||
本规范描述了用于将知识加载到 TrustGraph 的命令行接口,使用户能够通过命令行工具从各种来源导入数据。该集成支持四个主要用例:
|
||||
|
||||
1. **[用例 1]**: [描述]
|
||||
2. **[用例 2]**: [描述]
|
||||
3. **[用例 3]**: [描述]
|
||||
4. **[用例 4]**: [描述]
|
||||
|
||||
## 目标
|
||||
|
||||
- **[目标 1]**: [描述]
|
||||
- **[目标 2]**: [描述]
|
||||
- **[目标 3]**: [描述]
|
||||
- **[目标 4]**: [描述]
|
||||
- **[目标 5]**: [描述]
|
||||
- **[目标 6]**: [描述]
|
||||
- **[目标 7]**: [描述]
|
||||
- **[目标 8]**: [描述]
|
||||
|
||||
## 背景
|
||||
|
||||
[描述当前状态以及本规范所解决的限制]
|
||||
|
||||
当前的限制包括:
|
||||
- [限制 1]
|
||||
- [限制 2]
|
||||
- [限制 3]
|
||||
- [限制 4]
|
||||
|
||||
本规范通过 [描述] 解决了这些差距。 通过 [功能],TrustGraph 可以:
|
||||
- [优势 1]
|
||||
- [优势 2]
|
||||
- [优势 3]
|
||||
- [优势 4]
|
||||
|
||||
## 技术设计
|
||||
|
||||
### 架构
|
||||
|
||||
命令行知识加载需要以下技术组件:
|
||||
|
||||
1. **[组件 1]**
|
||||
- [组件功能描述]
|
||||
- [主要特性]
|
||||
- [集成点]
|
||||
|
||||
模块: [module-path]
|
||||
|
||||
2. **[组件 2]**
|
||||
- [组件功能描述]
|
||||
- [主要特性]
|
||||
- [集成点]
|
||||
|
||||
模块: [module-path]
|
||||
|
||||
3. **[组件 3]**
|
||||
- [组件功能描述]
|
||||
- [主要特性]
|
||||
- [集成点]
|
||||
|
||||
模块: [module-path]
|
||||
|
||||
### 数据模型
|
||||
|
||||
#### [数据模型 1]
|
||||
|
||||
[数据模型和结构的描述]
|
||||
|
||||
示例:
|
||||
```
|
||||
[Example data structure]
|
||||
```
|
||||
|
||||
这种方法允许:
|
||||
- [Benefit 1]
|
||||
- [Benefit 2]
|
||||
- [Benefit 3]
|
||||
- [Benefit 4]
|
||||
|
||||
### APIs
|
||||
|
||||
新的 API:
|
||||
- [API description 1]
|
||||
- [API description 2]
|
||||
- [API description 3]
|
||||
|
||||
修改后的 API:
|
||||
- [Modified API 1] - [Description of changes]
|
||||
- [Modified API 2] - [Description of changes]
|
||||
|
||||
### 实现细节
|
||||
|
||||
[Implementation approach and conventions]
|
||||
|
||||
[Additional implementation notes]
|
||||
|
||||
## 安全性考虑
|
||||
|
||||
[Security considerations specific to this implementation]
|
||||
|
||||
## 性能考虑
|
||||
|
||||
[Performance considerations and potential bottlenecks]
|
||||
|
||||
## 测试策略
|
||||
|
||||
[Testing approach and strategy]
|
||||
|
||||
## 迁移计划
|
||||
|
||||
[Migration strategy if applicable]
|
||||
|
||||
## 时间线
|
||||
|
||||
[Timeline information if specified]
|
||||
|
||||
## 待解决问题
|
||||
|
||||
- [Open question 1]
|
||||
- [Open question 2]
|
||||
|
||||
## 参考文献
|
||||
|
||||
[References if applicable]
|
||||
280
docs/tech-specs/agent-explainability.ar.md
Normal file
280
docs/tech-specs/agent-explainability.ar.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
---
|
||||
layout: default
|
||||
title: "شرح عمل الوكيل: تسجيل المصدر"
|
||||
parent: "Arabic (Beta)"
|
||||
---
|
||||
|
||||
# شرح عمل الوكيل: تسجيل المصدر
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
أضف تسجيل المصدر إلى حلقة الوكيل في React حتى يمكن تتبع جلسات الوكيل وتصحيحها باستخدام نفس البنية التحتية للشرح كما هو الحال في GraphRAG.
|
||||
|
||||
**قرارات التصميم:**
|
||||
الكتابة إلى `urn:graph:retrieval` (رسم بياني للشرح العام)
|
||||
سلسلة اعتماد خطية في الوقت الحالي (تحليل N → تم اشتقاقه من → تحليل N-1)
|
||||
الأدوات هي صناديق سوداء (تسجيل الإدخال/الإخراج فقط)
|
||||
دعم الرسم البياني الموجه غير المتصل (DAG) مؤجل للتكرار المستقبلي
|
||||
|
||||
## أنواع الكيانات
|
||||
|
||||
يستخدم كل من GraphRAG والوكيل PROV-O كعلم الوجود الأساسي مع أنواع فرعية خاصة بـ TrustGraph:
|
||||
|
||||
### أنواع GraphRAG
|
||||
| الكيان | نوع PROV-O | أنواع TG | الوصف |
|
||||
|--------|-------------|----------|-------------|
|
||||
| سؤال | `prov:Activity` | `tg:Question`, `tg:GraphRagQuestion` | استعلام المستخدم |
|
||||
| استكشاف | `prov:Entity` | `tg:Exploration` | الحواف المستردة من الرسم البياني المعرفي |
|
||||
| تركيز | `prov:Entity` | `tg:Focus` | الحواف المحددة مع الاستدلال |
|
||||
| توليف | `prov:Entity` | `tg:Synthesis` | الإجابة النهائية |
|
||||
|
||||
### أنواع الوكيل
|
||||
| الكيان | نوع PROV-O | أنواع TG | الوصف |
|
||||
|--------|-------------|----------|-------------|
|
||||
| سؤال | `prov:Activity` | `tg:Question`, `tg:AgentQuestion` | استعلام المستخدم |
|
||||
| تحليل | `prov:Entity` | `tg:Analysis` | كل دورة تفكير/فعل/ملاحظة |
|
||||
| استنتاج | `prov:Entity` | `tg:Conclusion` | الإجابة النهائية |
|
||||
|
||||
### أنواع RAG للوثائق
|
||||
| الكيان | نوع PROV-O | أنواع TG | الوصف |
|
||||
|--------|-------------|----------|-------------|
|
||||
| سؤال | `prov:Activity` | `tg:Question`, `tg:DocRagQuestion` | استعلام المستخدم |
|
||||
| استكشاف | `prov:Entity` | `tg:Exploration` | أجزاء مستردة من مستودع المستندات |
|
||||
| توليف | `prov:Entity` | `tg:Synthesis` | الإجابة النهائية |
|
||||
|
||||
**ملاحظة:** يستخدم RAG للوثائق مجموعة فرعية من أنواع GraphRAG (لا توجد خطوة "تركيز" نظرًا لعدم وجود مرحلة اختيار/استدلال للحواف).
|
||||
|
||||
### أنواع فرعية للأسئلة
|
||||
|
||||
تشترك جميع كيانات "سؤال" في `tg:Question` كنوع أساسي ولكنها تحتوي على نوع فرعي محدد لتحديد آلية الاسترداد:
|
||||
|
||||
| النوع الفرعي | نمط URI | الآلية |
|
||||
|---------|-------------|-----------|
|
||||
| `tg:GraphRagQuestion` | `urn:trustgraph:question:{uuid}` | RAG للرسم البياني المعرفي |
|
||||
| `tg:DocRagQuestion` | `urn:trustgraph:docrag:{uuid}` | RAG للوثائق/الأجزاء |
|
||||
| `tg:AgentQuestion` | `urn:trustgraph:agent:{uuid}` | وكيل ReAct |
|
||||
|
||||
يتيح ذلك الاستعلام عن جميع الأسئلة عبر `tg:Question` مع التصفية حسب آلية معينة عبر النوع الفرعي.
|
||||
|
||||
## نموذج المصدر
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:agent:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis1 (urn:trustgraph:agent:{uuid}/i1)
|
||||
│
|
||||
│ tg:thought = "I need to query the knowledge base..."
|
||||
│ tg:action = "knowledge-query"
|
||||
│ tg:arguments = {"question": "..."}
|
||||
│ tg:observation = "Result from tool..."
|
||||
│ rdf:type = prov:Entity, tg:Analysis
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis2 (urn:trustgraph:agent:{uuid}/i2)
|
||||
│ ...
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Conclusion (urn:trustgraph:agent:{uuid}/final)
|
||||
│
|
||||
│ tg:answer = "The final response..."
|
||||
│ rdf:type = prov:Entity, tg:Conclusion
|
||||
```
|
||||
|
||||
### نموذج تتبع أصل المستندات (Document RAG Provenance Model)
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:docrag:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasGeneratedBy
|
||||
│
|
||||
Exploration (urn:trustgraph:docrag:{uuid}/exploration)
|
||||
│
|
||||
│ tg:chunkCount = 5
|
||||
│ tg:selectedChunk = "chunk-id-1"
|
||||
│ tg:selectedChunk = "chunk-id-2"
|
||||
│ ...
|
||||
│ rdf:type = prov:Entity, tg:Exploration
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Synthesis (urn:trustgraph:docrag:{uuid}/synthesis)
|
||||
│
|
||||
│ tg:content = "The synthesized answer..."
|
||||
│ rdf:type = prov:Entity, tg:Synthesis
|
||||
```
|
||||
|
||||
## التغييرات المطلوبة
|
||||
|
||||
### 1. تغييرات المخطط
|
||||
|
||||
**الملف:** `trustgraph-base/trustgraph/schema/services/agent.py`
|
||||
|
||||
أضف الحقول `session_id` و `collection` إلى `AgentRequest`:
|
||||
```python
|
||||
@dataclass
|
||||
class AgentRequest:
|
||||
question: str = ""
|
||||
state: str = ""
|
||||
group: list[str] | None = None
|
||||
history: list[AgentStep] = field(default_factory=list)
|
||||
user: str = ""
|
||||
collection: str = "default" # NEW: Collection for provenance traces
|
||||
streaming: bool = False
|
||||
session_id: str = "" # NEW: For provenance tracking across iterations
|
||||
```
|
||||
|
||||
**الملف:** `trustgraph-base/trustgraph/messaging/translators/agent.py`
|
||||
|
||||
تحديث المترجم للتعامل مع `session_id` و `collection` في كل من `to_pulsar()` و `from_pulsar()`.
|
||||
|
||||
### 2. إضافة مُنتج الشفافية إلى خدمة الوكيل
|
||||
|
||||
**الملف:** `trustgraph-flow/trustgraph/agent/react/service.py`
|
||||
|
||||
تسجيل مُنتج "الشفافية" (بنفس النمط مثل GraphRAG):
|
||||
```python
|
||||
from ... base import ProducerSpec
|
||||
from ... schema import Triples
|
||||
|
||||
# In __init__:
|
||||
self.register_specification(
|
||||
ProducerSpec(
|
||||
name = "explainability",
|
||||
schema = Triples,
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### 3. توليد الثلاثيات المتعلقة بالأصل.
|
||||
|
||||
**الملف:** `trustgraph-base/trustgraph/provenance/agent.py`
|
||||
|
||||
إنشاء دوال مساعدة (مشابهة لدوال `question_triples` و `exploration_triples`، إلخ في GraphRAG):
|
||||
```python
|
||||
def agent_session_triples(session_uri, query, timestamp):
|
||||
"""Generate triples for agent Question."""
|
||||
return [
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=PROV_ACTIVITY),
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=TG_QUESTION),
|
||||
Triple(s=session_uri, p=TG_QUERY, o=query),
|
||||
Triple(s=session_uri, p=PROV_STARTED_AT_TIME, o=timestamp),
|
||||
]
|
||||
|
||||
def agent_iteration_triples(iteration_uri, parent_uri, thought, action, arguments, observation):
|
||||
"""Generate triples for one Analysis step."""
|
||||
return [
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=TG_ANALYSIS),
|
||||
Triple(s=iteration_uri, p=TG_THOUGHT, o=thought),
|
||||
Triple(s=iteration_uri, p=TG_ACTION, o=action),
|
||||
Triple(s=iteration_uri, p=TG_ARGUMENTS, o=json.dumps(arguments)),
|
||||
Triple(s=iteration_uri, p=TG_OBSERVATION, o=observation),
|
||||
Triple(s=iteration_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
|
||||
def agent_final_triples(final_uri, parent_uri, answer):
|
||||
"""Generate triples for Conclusion."""
|
||||
return [
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=TG_CONCLUSION),
|
||||
Triple(s=final_uri, p=TG_ANSWER, o=answer),
|
||||
Triple(s=final_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
```
|
||||
|
||||
### 4. تعريفات الأنواع
|
||||
|
||||
**الملف:** `trustgraph-base/trustgraph/provenance/namespaces.py`
|
||||
|
||||
أضف أنواع الكيانات الخاصة بالتفسير والعبارات الخاصة بالوكيل:
|
||||
```python
|
||||
# Explainability entity types (used by both GraphRAG and Agent)
|
||||
TG_QUESTION = TG + "Question"
|
||||
TG_EXPLORATION = TG + "Exploration"
|
||||
TG_FOCUS = TG + "Focus"
|
||||
TG_SYNTHESIS = TG + "Synthesis"
|
||||
TG_ANALYSIS = TG + "Analysis"
|
||||
TG_CONCLUSION = TG + "Conclusion"
|
||||
|
||||
# Agent predicates
|
||||
TG_THOUGHT = TG + "thought"
|
||||
TG_ACTION = TG + "action"
|
||||
TG_ARGUMENTS = TG + "arguments"
|
||||
TG_OBSERVATION = TG + "observation"
|
||||
TG_ANSWER = TG + "answer"
|
||||
```
|
||||
|
||||
## الملفات التي تم تعديلها
|
||||
|
||||
| الملف | التغيير |
|
||||
|------|--------|
|
||||
| `trustgraph-base/trustgraph/schema/services/agent.py` | إضافة session_id و collection إلى AgentRequest |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/agent.py` | تحديث المترجم للحقول الجديدة |
|
||||
| `trustgraph-base/trustgraph/provenance/namespaces.py` | إضافة أنواع الكيانات، وعبارات الوكيل، وأنواع Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/triples.py` | إضافة أنواع TG إلى أدوات بناء الثلاثيات GraphRAG، وإضافة أدوات بناء الثلاثيات Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/uris.py` | إضافة مولدات URI لـ Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/__init__.py` | تصدير الأنواع والعبارات الجديدة ووظائف Document RAG |
|
||||
| `trustgraph-base/trustgraph/schema/services/retrieval.py` | إضافة explain_id و explain_graph إلى DocumentRagResponse |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/retrieval.py` | تحديث DocumentRagResponseTranslator للحقول الخاصة بالقدرة على الشرح |
|
||||
| `trustgraph-flow/trustgraph/agent/react/service.py` | إضافة منطق الإنتاج والتسجيل الخاص بالقدرة على الشرح |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` | إضافة استدعاء رد (callback) خاص بالقدرة على الشرح وإصدار ثلاثيات المصدر |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` | إضافة مُنتج القدرة على الشرح وربطه بالاستدعاء الردي |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | معالجة أنواع تتبع الوكيل |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | عرض جلسات الوكيل جنبًا إلى جنب مع GraphRAG |
|
||||
|
||||
## الملفات التي تم إنشاؤها
|
||||
|
||||
| الملف | الغرض |
|
||||
|------|---------|
|
||||
| `trustgraph-base/trustgraph/provenance/agent.py` | مولدات ثلاثيات خاصة بالوكيل |
|
||||
|
||||
## تحديثات واجهة سطر الأوامر (CLI)
|
||||
|
||||
**الكشف:** كل من GraphRAG والأسئلة الخاصة بالوكيل لهما نوع `tg:Question`. يتم التمييز بينهما بواسطة:
|
||||
1. نمط URI: `urn:trustgraph:agent:` مقابل `urn:trustgraph:question:`
|
||||
2. الكيانات المشتقة: `tg:Analysis` (الوكيل) مقابل `tg:Exploration` (GraphRAG)
|
||||
|
||||
**`list_explain_traces.py`:**
|
||||
يعرض عمود النوع (الوكيل مقابل GraphRAG)
|
||||
|
||||
**`show_explain_trace.py`:**
|
||||
يكتشف تلقائيًا نوع التتبع
|
||||
يعرض عرض الوكيل: سؤال → خطوة(ات) تحليل → استنتاج
|
||||
|
||||
## التوافق مع الإصدارات السابقة
|
||||
|
||||
`session_id` افتراضيًا إلى `""` - تعمل الطلبات القديمة، ولكن لن تحتوي على معلومات المصدر |
|
||||
`collection` افتراضيًا إلى `"default"` - حل بديل معقول |
|
||||
تتعامل واجهة سطر الأوامر (CLI) بأمان مع كلا نوعي التتبع |
|
||||
|
||||
## التحقق
|
||||
|
||||
```bash
|
||||
# Run an agent query
|
||||
tg-invoke-agent -q "What is the capital of France?"
|
||||
|
||||
# List traces (should show agent sessions with Type column)
|
||||
tg-list-explain-traces -U trustgraph -C default
|
||||
|
||||
# Show agent trace
|
||||
tg-show-explain-trace "urn:trustgraph:agent:xxx"
|
||||
```
|
||||
|
||||
## الأعمال المستقبلية (ليست جزءًا من هذا التعديل)
|
||||
|
||||
تبعيات الرسم البياني الموجه (عندما يعتمد التحليل N على نتائج تحليلات سابقة متعددة)
|
||||
ربط المصادر الخاص بالأدوات (KnowledgeQuery ← تتبع GraphRAG الخاص به)
|
||||
إرسال المصادر بشكل مستمر (إرسال البيانات أثناء العمل، وليس دفعة واحدة في النهاية)
|
||||
280
docs/tech-specs/agent-explainability.es.md
Normal file
280
docs/tech-specs/agent-explainability.es.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Explicabilidad del Agente: Registro de Origen"
|
||||
parent: "Spanish (Beta)"
|
||||
---
|
||||
|
||||
# Explicabilidad del Agente: Registro de Origen
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Resumen
|
||||
|
||||
Agregar el registro de origen al bucle del agente de React para que las sesiones del agente puedan ser rastreadas y depuradas utilizando la misma infraestructura de explicabilidad que GraphRAG.
|
||||
|
||||
**Decisiones de Diseño:**
|
||||
- Escribir en `urn:graph:retrieval` (grafo de explicabilidad genérico)
|
||||
- Cadena de dependencia lineal por ahora (análisis N → derivado de → análisis N-1)
|
||||
- Las herramientas son cajas negras opacas (registrar solo la entrada/salida)
|
||||
- El soporte de DAG se pospone a una iteración futura
|
||||
|
||||
## Tipos de Entidades
|
||||
|
||||
Tanto GraphRAG como Agent utilizan PROV-O como la ontología base con subtipos específicos de TrustGraph:
|
||||
|
||||
### Tipos de GraphRAG
|
||||
| Entidad | Tipo PROV-O | Tipos TG | Descripción |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Pregunta | `prov:Activity` | `tg:Question`, `tg:GraphRagQuestion` | La consulta del usuario |
|
||||
| Exploración | `prov:Entity` | `tg:Exploration` | Bordes recuperados del grafo de conocimiento |
|
||||
| Enfoque | `prov:Entity` | `tg:Focus` | Bordes seleccionados con razonamiento |
|
||||
| Síntesis | `prov:Entity` | `tg:Synthesis` | Respuesta final |
|
||||
|
||||
### Tipos de Agente
|
||||
| Entidad | Tipo PROV-O | Tipos TG | Descripción |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Pregunta | `prov:Activity` | `tg:Question`, `tg:AgentQuestion` | La consulta del usuario |
|
||||
| Análisis | `prov:Entity` | `tg:Analysis` | Cada ciclo de pensar/actuar/observar |
|
||||
| Conclusión | `prov:Entity` | `tg:Conclusion` | Respuesta final |
|
||||
|
||||
### Tipos de Document RAG
|
||||
| Entidad | Tipo PROV-O | Tipos TG | Descripción |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Pregunta | `prov:Activity` | `tg:Question`, `tg:DocRagQuestion` | La consulta del usuario |
|
||||
| Exploración | `prov:Entity` | `tg:Exploration` | Fragmentos recuperados del almacén de documentos |
|
||||
| Síntesis | `prov:Entity` | `tg:Synthesis` | Respuesta final |
|
||||
|
||||
**Nota:** Document RAG utiliza un subconjunto de los tipos de GraphRAG (no hay un paso de "Enfoque" ya que no hay una fase de selección/razonamiento de bordes).
|
||||
|
||||
### Subtipos de Pregunta
|
||||
|
||||
Todas las entidades de "Pregunta" comparten `tg:Question` como un tipo base, pero tienen un subtipo específico para identificar el mecanismo de recuperación:
|
||||
|
||||
| Subtipo | Patrón URI | Mecanismo |
|
||||
|---------|-------------|-----------|
|
||||
| `tg:GraphRagQuestion` | `urn:trustgraph:question:{uuid}` | RAG de grafo de conocimiento |
|
||||
| `tg:DocRagQuestion` | `urn:trustgraph:docrag:{uuid}` | RAG de documento/fragmento |
|
||||
| `tg:AgentQuestion` | `urn:trustgraph:agent:{uuid}` | Agente ReAct |
|
||||
|
||||
Esto permite consultar todas las preguntas a través de `tg:Question` mientras se filtra por un mecanismo específico a través del subtipo.
|
||||
|
||||
## Modelo de Origen
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:agent:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis1 (urn:trustgraph:agent:{uuid}/i1)
|
||||
│
|
||||
│ tg:thought = "I need to query the knowledge base..."
|
||||
│ tg:action = "knowledge-query"
|
||||
│ tg:arguments = {"question": "..."}
|
||||
│ tg:observation = "Result from tool..."
|
||||
│ rdf:type = prov:Entity, tg:Analysis
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis2 (urn:trustgraph:agent:{uuid}/i2)
|
||||
│ ...
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Conclusion (urn:trustgraph:agent:{uuid}/final)
|
||||
│
|
||||
│ tg:answer = "The final response..."
|
||||
│ rdf:type = prov:Entity, tg:Conclusion
|
||||
```
|
||||
|
||||
### Modelo de Origen (Provenance) del Documento RAG
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:docrag:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasGeneratedBy
|
||||
│
|
||||
Exploration (urn:trustgraph:docrag:{uuid}/exploration)
|
||||
│
|
||||
│ tg:chunkCount = 5
|
||||
│ tg:selectedChunk = "chunk-id-1"
|
||||
│ tg:selectedChunk = "chunk-id-2"
|
||||
│ ...
|
||||
│ rdf:type = prov:Entity, tg:Exploration
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Synthesis (urn:trustgraph:docrag:{uuid}/synthesis)
|
||||
│
|
||||
│ tg:content = "The synthesized answer..."
|
||||
│ rdf:type = prov:Entity, tg:Synthesis
|
||||
```
|
||||
|
||||
## Cambios Requeridos
|
||||
|
||||
### 1. Cambios en el Esquema
|
||||
|
||||
**Archivo:** `trustgraph-base/trustgraph/schema/services/agent.py`
|
||||
|
||||
Agregar los campos `session_id` y `collection` a `AgentRequest`:
|
||||
```python
|
||||
@dataclass
|
||||
class AgentRequest:
|
||||
question: str = ""
|
||||
state: str = ""
|
||||
group: list[str] | None = None
|
||||
history: list[AgentStep] = field(default_factory=list)
|
||||
user: str = ""
|
||||
collection: str = "default" # NEW: Collection for provenance traces
|
||||
streaming: bool = False
|
||||
session_id: str = "" # NEW: For provenance tracking across iterations
|
||||
```
|
||||
|
||||
**Archivo:** `trustgraph-base/trustgraph/messaging/translators/agent.py`
|
||||
|
||||
Actualizar el traductor para manejar `session_id` y `collection` tanto en `to_pulsar()` como en `from_pulsar()`.
|
||||
|
||||
### 2. Agregar un Productor de Explicabilidad al Servicio de Agente
|
||||
|
||||
**Archivo:** `trustgraph-flow/trustgraph/agent/react/service.py`
|
||||
|
||||
Registrar un productor de "explicabilidad" (mismo patrón que GraphRAG):
|
||||
```python
|
||||
from ... base import ProducerSpec
|
||||
from ... schema import Triples
|
||||
|
||||
# In __init__:
|
||||
self.register_specification(
|
||||
ProducerSpec(
|
||||
name = "explainability",
|
||||
schema = Triples,
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### 3. Generación de Triples de Proveniencia
|
||||
|
||||
**Archivo:** `trustgraph-base/trustgraph/provenance/agent.py`
|
||||
|
||||
Crear funciones auxiliares (similares a `question_triples`, `exploration_triples`, etc. de GraphRAG):
|
||||
```python
|
||||
def agent_session_triples(session_uri, query, timestamp):
|
||||
"""Generate triples for agent Question."""
|
||||
return [
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=PROV_ACTIVITY),
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=TG_QUESTION),
|
||||
Triple(s=session_uri, p=TG_QUERY, o=query),
|
||||
Triple(s=session_uri, p=PROV_STARTED_AT_TIME, o=timestamp),
|
||||
]
|
||||
|
||||
def agent_iteration_triples(iteration_uri, parent_uri, thought, action, arguments, observation):
|
||||
"""Generate triples for one Analysis step."""
|
||||
return [
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=TG_ANALYSIS),
|
||||
Triple(s=iteration_uri, p=TG_THOUGHT, o=thought),
|
||||
Triple(s=iteration_uri, p=TG_ACTION, o=action),
|
||||
Triple(s=iteration_uri, p=TG_ARGUMENTS, o=json.dumps(arguments)),
|
||||
Triple(s=iteration_uri, p=TG_OBSERVATION, o=observation),
|
||||
Triple(s=iteration_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
|
||||
def agent_final_triples(final_uri, parent_uri, answer):
|
||||
"""Generate triples for Conclusion."""
|
||||
return [
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=TG_CONCLUSION),
|
||||
Triple(s=final_uri, p=TG_ANSWER, o=answer),
|
||||
Triple(s=final_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
```
|
||||
|
||||
### 4. Definiciones de tipo
|
||||
|
||||
**Archivo:** `trustgraph-base/trustgraph/provenance/namespaces.py`
|
||||
|
||||
Agregar tipos de entidad de explicabilidad y predicados de agente:
|
||||
```python
|
||||
# Explainability entity types (used by both GraphRAG and Agent)
|
||||
TG_QUESTION = TG + "Question"
|
||||
TG_EXPLORATION = TG + "Exploration"
|
||||
TG_FOCUS = TG + "Focus"
|
||||
TG_SYNTHESIS = TG + "Synthesis"
|
||||
TG_ANALYSIS = TG + "Analysis"
|
||||
TG_CONCLUSION = TG + "Conclusion"
|
||||
|
||||
# Agent predicates
|
||||
TG_THOUGHT = TG + "thought"
|
||||
TG_ACTION = TG + "action"
|
||||
TG_ARGUMENTS = TG + "arguments"
|
||||
TG_OBSERVATION = TG + "observation"
|
||||
TG_ANSWER = TG + "answer"
|
||||
```
|
||||
|
||||
## Archivos Modificados
|
||||
|
||||
| Archivo | Cambio |
|
||||
|------|--------|
|
||||
| `trustgraph-base/trustgraph/schema/services/agent.py` | Agregar session_id y collection a AgentRequest |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/agent.py` | Actualizar el traductor para nuevos campos |
|
||||
| `trustgraph-base/trustgraph/provenance/namespaces.py` | Agregar tipos de entidad, predicados de agente y predicados de Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/triples.py` | Agregar tipos de TG a los constructores de triples de GraphRAG, agregar constructores de triples de Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/uris.py` | Agregar generadores de URI de Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/__init__.py` | Exportar nuevos tipos, predicados y funciones de Document RAG |
|
||||
| `trustgraph-base/trustgraph/schema/services/retrieval.py` | Agregar explain_id y explain_graph a DocumentRagResponse |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/retrieval.py` | Actualizar DocumentRagResponseTranslator para campos de explicabilidad |
|
||||
| `trustgraph-flow/trustgraph/agent/react/service.py` | Agregar lógica de productor y registro de explicabilidad |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` | Agregar devolución de llamada de explicabilidad y emitir triples de procedencia |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` | Agregar productor de explicabilidad y conectar la devolución de llamada |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | Manejar tipos de traza de agente |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | Listar sesiones de agente junto con GraphRAG |
|
||||
|
||||
## Archivos Creados
|
||||
|
||||
| Archivo | Propósito |
|
||||
|------|---------|
|
||||
| `trustgraph-base/trustgraph/provenance/agent.py` | Generadores de triples específicos del agente |
|
||||
|
||||
## Actualizaciones de la CLI
|
||||
|
||||
**Detección:** Tanto GraphRAG como las Preguntas del Agente tienen el tipo `tg:Question`. Se distinguen por:
|
||||
1. Patrón de URI: `urn:trustgraph:agent:` vs `urn:trustgraph:question:`
|
||||
2. Entidades derivadas: `tg:Analysis` (agente) vs `tg:Exploration` (GraphRAG)
|
||||
|
||||
**`list_explain_traces.py`:**
|
||||
- Muestra la columna Tipo (Agente vs GraphRAG)
|
||||
|
||||
**`show_explain_trace.py`:**
|
||||
- Detecta automáticamente el tipo de traza
|
||||
- La representación del agente muestra: Pregunta → Paso(s) de análisis → Conclusión
|
||||
|
||||
## Compatibilidad con versiones anteriores
|
||||
|
||||
- `session_id` por defecto es `""` - las solicitudes antiguas funcionan, pero no tendrán procedencia
|
||||
- `collection` por defecto es `"default"` - alternativa razonable
|
||||
- La CLI maneja correctamente ambos tipos de traza
|
||||
|
||||
## Verificación
|
||||
|
||||
```bash
|
||||
# Run an agent query
|
||||
tg-invoke-agent -q "What is the capital of France?"
|
||||
|
||||
# List traces (should show agent sessions with Type column)
|
||||
tg-list-explain-traces -U trustgraph -C default
|
||||
|
||||
# Show agent trace
|
||||
tg-show-explain-trace "urn:trustgraph:agent:xxx"
|
||||
```
|
||||
|
||||
## Trabajo Futuro (No Incluido en esta Solicitud de Incorporación)
|
||||
|
||||
- Dependencias de DAG (cuando el análisis N utiliza resultados de múltiples análisis anteriores)
|
||||
- Enlace de procedencia específico de la herramienta (KnowledgeQuery → su traza GraphRAG)
|
||||
- Emisión de procedencia en streaming (emitir a medida que se avanza, no en lote al final)
|
||||
280
docs/tech-specs/agent-explainability.he.md
Normal file
280
docs/tech-specs/agent-explainability.he.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
---
|
||||
layout: default
|
||||
title: "הסברתיות של סוכן: רישום מקורות"
|
||||
parent: "Hebrew (Beta)"
|
||||
---
|
||||
|
||||
# הסברתיות של סוכן: רישום מקורות
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## סקירה כללית
|
||||
|
||||
הוספת רישום מקורות ללולאת הסוכן של React כך שניתן יהיה לעקוב אחר סשנים של סוכנים ולבצע ניפוי באגים באמצעות אותה תשתית הסברתיות כמו GraphRAG.
|
||||
|
||||
**החלטות עיצוב:**
|
||||
כתיבה ל-`urn:graph:retrieval` (גרף הסברתיות גנרי)
|
||||
שרשרת תלות ליניארית כרגע (ניתוח N → נגזר מ → ניתוח N-1)
|
||||
כלים הם תיבות שחורות (רישום קלט/פלט בלבד)
|
||||
תמיכה ב-DAG (גרף מכוון) נדחית למהלך עתידי
|
||||
|
||||
## סוגי ישויות
|
||||
|
||||
גם GraphRAG וגם Agent משתמשים ב-PROV-O כאונטולוגיה בסיסית עם תת-סוגים ספציפיים ל-TrustGraph:
|
||||
|
||||
### סוגי GraphRAG
|
||||
| ישות | סוג PROV-O | סוגי TG | תיאור |
|
||||
|--------|-------------|----------|-------------|
|
||||
| שאלה | `prov:Activity` | `tg:Question`, `tg:GraphRagQuestion` | השאלה של המשתמש |
|
||||
| חקירה | `prov:Entity` | `tg:Exploration` | צמתים שאוחזרו מגרף ידע |
|
||||
| מיקוד | `prov:Entity` | `tg:Focus` | צמתים שנבחרו עם נימוק |
|
||||
| סינתזה | `prov:Entity` | `tg:Synthesis` | תשובה סופית |
|
||||
|
||||
### סוגי סוכן
|
||||
| ישות | סוג PROV-O | סוגי TG | תיאור |
|
||||
|--------|-------------|----------|-------------|
|
||||
| שאלה | `prov:Activity` | `tg:Question`, `tg:AgentQuestion` | השאלה של המשתמש |
|
||||
| ניתוח | `prov:Entity` | `tg:Analysis` | כל מחזור חשיבה/פעולה/תצפית |
|
||||
| מסקנה | `prov:Entity` | `tg:Conclusion` | תשובה סופית |
|
||||
|
||||
### סוגי RAG של מסמכים
|
||||
| ישות | סוג PROV-O | סוגי TG | תיאור |
|
||||
|--------|-------------|----------|-------------|
|
||||
| שאלה | `prov:Activity` | `tg:Question`, `tg:DocRagQuestion` | השאלה של המשתמש |
|
||||
| חקירה | `prov:Entity` | `tg:Exploration` | חלקים שאוחזרו מחנות מסמכים |
|
||||
| סינתזה | `prov:Entity` | `tg:Synthesis` | תשובה סופית |
|
||||
|
||||
**הערה:** RAG של מסמכים משתמש בתת-קבוצה של סוגים של GraphRAG (אין שלב מיקוד מכיוון שאין שלב בחירת/נימוק צמתים).
|
||||
|
||||
### תת-סוגים של שאלה
|
||||
|
||||
כל ישויות השאלה חולקות את `tg:Question` כסוג בסיסי אך יש להן תת-סוג ספציפי כדי לזהות את מנגנון השליפה:
|
||||
|
||||
| תת-סוג | תבנית URI | מנגנון |
|
||||
|---------|-------------|-----------|
|
||||
| `tg:GraphRagQuestion` | `urn:trustgraph:question:{uuid}` | RAG של גרף ידע |
|
||||
| `tg:DocRagQuestion` | `urn:trustgraph:docrag:{uuid}` | RAG של מסמכים/חלקים |
|
||||
| `tg:AgentQuestion` | `urn:trustgraph:agent:{uuid}` | סוכן ReAct |
|
||||
|
||||
זה מאפשר שאילתא של כל השאלות באמצעות `tg:Question` תוך סינון לפי מנגנון ספציפי באמצעות תת-הסוג.
|
||||
|
||||
## מודל מקורות
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:agent:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis1 (urn:trustgraph:agent:{uuid}/i1)
|
||||
│
|
||||
│ tg:thought = "I need to query the knowledge base..."
|
||||
│ tg:action = "knowledge-query"
|
||||
│ tg:arguments = {"question": "..."}
|
||||
│ tg:observation = "Result from tool..."
|
||||
│ rdf:type = prov:Entity, tg:Analysis
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis2 (urn:trustgraph:agent:{uuid}/i2)
|
||||
│ ...
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Conclusion (urn:trustgraph:agent:{uuid}/final)
|
||||
│
|
||||
│ tg:answer = "The final response..."
|
||||
│ rdf:type = prov:Entity, tg:Conclusion
|
||||
```
|
||||
|
||||
### מודל מקור (Provenance) של מסמכים בשיטת RAG
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:docrag:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasGeneratedBy
|
||||
│
|
||||
Exploration (urn:trustgraph:docrag:{uuid}/exploration)
|
||||
│
|
||||
│ tg:chunkCount = 5
|
||||
│ tg:selectedChunk = "chunk-id-1"
|
||||
│ tg:selectedChunk = "chunk-id-2"
|
||||
│ ...
|
||||
│ rdf:type = prov:Entity, tg:Exploration
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Synthesis (urn:trustgraph:docrag:{uuid}/synthesis)
|
||||
│
|
||||
│ tg:content = "The synthesized answer..."
|
||||
│ rdf:type = prov:Entity, tg:Synthesis
|
||||
```
|
||||
|
||||
## שינויים נדרשים
|
||||
|
||||
### 1. שינויים בסכימה
|
||||
|
||||
**קובץ:** `trustgraph-base/trustgraph/schema/services/agent.py`
|
||||
|
||||
הוסף את השדות `session_id` ו-`collection` ל-`AgentRequest`:
|
||||
```python
|
||||
@dataclass
|
||||
class AgentRequest:
|
||||
question: str = ""
|
||||
state: str = ""
|
||||
group: list[str] | None = None
|
||||
history: list[AgentStep] = field(default_factory=list)
|
||||
user: str = ""
|
||||
collection: str = "default" # NEW: Collection for provenance traces
|
||||
streaming: bool = False
|
||||
session_id: str = "" # NEW: For provenance tracking across iterations
|
||||
```
|
||||
|
||||
**קובץ:** `trustgraph-base/trustgraph/messaging/translators/agent.py`
|
||||
|
||||
עדכון המתרגם כדי לטפל ב-`session_id` וב-`collection` הן ב-`to_pulsar()` והן ב-`from_pulsar()`.
|
||||
|
||||
### 2. הוספת יצרן הסברות לשירות הסוכנים
|
||||
|
||||
**קובץ:** `trustgraph-flow/trustgraph/agent/react/service.py`
|
||||
|
||||
רישום יצרן "הסברות" (באותו דפוס כמו GraphRAG):
|
||||
```python
|
||||
from ... base import ProducerSpec
|
||||
from ... schema import Triples
|
||||
|
||||
# In __init__:
|
||||
self.register_specification(
|
||||
ProducerSpec(
|
||||
name = "explainability",
|
||||
schema = Triples,
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### 3. יצירת משולש מוצא
|
||||
|
||||
**קובץ:** `trustgraph-base/trustgraph/provenance/agent.py`
|
||||
|
||||
צור פונקציות עזר (בדומה ל-`question_triples`, `exploration_triples` וכו' של GraphRAG):
|
||||
```python
|
||||
def agent_session_triples(session_uri, query, timestamp):
|
||||
"""Generate triples for agent Question."""
|
||||
return [
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=PROV_ACTIVITY),
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=TG_QUESTION),
|
||||
Triple(s=session_uri, p=TG_QUERY, o=query),
|
||||
Triple(s=session_uri, p=PROV_STARTED_AT_TIME, o=timestamp),
|
||||
]
|
||||
|
||||
def agent_iteration_triples(iteration_uri, parent_uri, thought, action, arguments, observation):
|
||||
"""Generate triples for one Analysis step."""
|
||||
return [
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=TG_ANALYSIS),
|
||||
Triple(s=iteration_uri, p=TG_THOUGHT, o=thought),
|
||||
Triple(s=iteration_uri, p=TG_ACTION, o=action),
|
||||
Triple(s=iteration_uri, p=TG_ARGUMENTS, o=json.dumps(arguments)),
|
||||
Triple(s=iteration_uri, p=TG_OBSERVATION, o=observation),
|
||||
Triple(s=iteration_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
|
||||
def agent_final_triples(final_uri, parent_uri, answer):
|
||||
"""Generate triples for Conclusion."""
|
||||
return [
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=TG_CONCLUSION),
|
||||
Triple(s=final_uri, p=TG_ANSWER, o=answer),
|
||||
Triple(s=final_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
```
|
||||
|
||||
### 4. הגדרות סוג
|
||||
|
||||
**קובץ:** `trustgraph-base/trustgraph/provenance/namespaces.py`
|
||||
|
||||
הוסף סוגי ישויות הסבר ופרדיקטים של סוכנים:
|
||||
```python
|
||||
# Explainability entity types (used by both GraphRAG and Agent)
|
||||
TG_QUESTION = TG + "Question"
|
||||
TG_EXPLORATION = TG + "Exploration"
|
||||
TG_FOCUS = TG + "Focus"
|
||||
TG_SYNTHESIS = TG + "Synthesis"
|
||||
TG_ANALYSIS = TG + "Analysis"
|
||||
TG_CONCLUSION = TG + "Conclusion"
|
||||
|
||||
# Agent predicates
|
||||
TG_THOUGHT = TG + "thought"
|
||||
TG_ACTION = TG + "action"
|
||||
TG_ARGUMENTS = TG + "arguments"
|
||||
TG_OBSERVATION = TG + "observation"
|
||||
TG_ANSWER = TG + "answer"
|
||||
```
|
||||
|
||||
## קבצים ששונו
|
||||
|
||||
| קובץ | שינוי |
|
||||
|------|--------|
|
||||
| `trustgraph-base/trustgraph/schema/services/agent.py` | הוספת session_id ו-collection ל-AgentRequest |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/agent.py` | עדכון מתרגם עבור שדות חדשים |
|
||||
| `trustgraph-base/trustgraph/provenance/namespaces.py` | הוספת סוגי ישויות, טענות של סוכן וטענות של Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/triples.py` | הוספת סוגי TG לבונים של משולשים של GraphRAG, הוספת בונים של משולשים של Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/uris.py` | הוספת יוצרי URI של Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/__init__.py` | ייצוא סוגים, טענות ופונקציות חדשות של Document RAG |
|
||||
| `trustgraph-base/trustgraph/schema/services/retrieval.py` | הוספת explain_id ו-explain_graph ל-DocumentRagResponse |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/retrieval.py` | עדכון DocumentRagResponseTranslator עבור שדות הסברתיות |
|
||||
| `trustgraph-flow/trustgraph/agent/react/service.py` | הוספת מפיק הסברתיות + לוגיקת הקלטה |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` | הוספת קריאה חוזרת של הסברתיות ופליטת משולשים של מקור |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` | הוספת מפיק הסברתיות וחיבור הקריאה החוזרת |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | טיפול בסוגי מעקב של סוכן |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | הצגת סשנים של סוכן לצד GraphRAG |
|
||||
|
||||
## קבצים שנוצרו
|
||||
|
||||
| קובץ | מטרה |
|
||||
|------|---------|
|
||||
| `trustgraph-base/trustgraph/provenance/agent.py` | יוצרי משולשים ספציפיים לסוכן |
|
||||
|
||||
## עדכוני CLI
|
||||
|
||||
**זיהוי:** גם לשאלות GraphRAG וגם לשאלות סוכן יש סוג `tg:Question`. מובחנים על ידי:
|
||||
1. תבנית URI: `urn:trustgraph:agent:` לעומת `urn:trustgraph:question:`
|
||||
2. ישויות נגזרות: `tg:Analysis` (סוכן) לעומת `tg:Exploration` (GraphRAG)
|
||||
|
||||
**`list_explain_traces.py`:**
|
||||
מציג את עמודת הסוג (סוכן לעומת GraphRAG)
|
||||
|
||||
**`show_explain_trace.py`:**
|
||||
מזהה אוטומטית את סוג המעקב
|
||||
הצגת סוכן מציגה: שאלה → שלב(ים) של ניתוח → מסקנה
|
||||
|
||||
## תאימות לאחור
|
||||
|
||||
`session_id` כברירת מחדל הוא `""` - בקשות ישנות עובדות, פשוט לא יהיו להן נתונים של מקור
|
||||
`collection` כברירת מחדל הוא `"default"` - חזרה סבירה
|
||||
ה-CLI מטפל בצורה חלקה בשני סוגי המעקב
|
||||
|
||||
## אימות
|
||||
|
||||
```bash
|
||||
# Run an agent query
|
||||
tg-invoke-agent -q "What is the capital of France?"
|
||||
|
||||
# List traces (should show agent sessions with Type column)
|
||||
tg-list-explain-traces -U trustgraph -C default
|
||||
|
||||
# Show agent trace
|
||||
tg-show-explain-trace "urn:trustgraph:agent:xxx"
|
||||
```
|
||||
|
||||
## עבודה עתידית (לא בבקשה הזו)
|
||||
|
||||
תלותיות DAG (כאשר ניתוח N משתמש בתוצאות ממספר ניתוחים קודמים)
|
||||
קישור מקורות מידע ספציפי לכלי (KnowledgeQuery → המעקב GraphRAG שלו)
|
||||
פליטת מקורות מידע בסטרימינג (לשלוח תוך כדי פעולה, ולא במקשה בסוף)
|
||||
280
docs/tech-specs/agent-explainability.hi.md
Normal file
280
docs/tech-specs/agent-explainability.hi.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
---
|
||||
layout: default
|
||||
title: "एजेंट स्पष्टता: उत्पत्ति रिकॉर्डिंग"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# एजेंट स्पष्टता: उत्पत्ति रिकॉर्डिंग
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## अवलोकन
|
||||
|
||||
रिएक्ट एजेंट लूप में उत्पत्ति रिकॉर्डिंग जोड़ें ताकि एजेंट सत्रों को ट्रैक और डीबग किया जा सके, जो कि ग्राफआरएजी के समान स्पष्टता बुनियादी ढांचे का उपयोग करके किया जा सके।
|
||||
|
||||
**डिजाइन निर्णय:**
|
||||
`urn:graph:retrieval` (सामान्य स्पष्टता ग्राफ) में लिखें
|
||||
फिलहाल रैखिक निर्भरता श्रृंखला (विश्लेषण N → wasDerivedFrom → विश्लेषण N-1)
|
||||
उपकरण अपार ब्लैक बॉक्स हैं (केवल इनपुट/आउटपुट रिकॉर्ड करें)
|
||||
डीएजी समर्थन भविष्य के पुनरावृत्ति के लिए स्थगित है
|
||||
|
||||
## इकाई प्रकार
|
||||
|
||||
ग्राफआरएजी और एजेंट दोनों ही ट्रस्टग्राफ-विशिष्ट उपप्रकारों के साथ पीआरओवी-ओ को आधार ऑन्टोलॉजी के रूप में उपयोग करते हैं:
|
||||
|
||||
### ग्राफआरएजी प्रकार
|
||||
| इकाई | पीआरओवी-ओ प्रकार | टीजी प्रकार | विवरण |
|
||||
|--------|-------------|----------|-------------|
|
||||
| प्रश्न | `prov:Activity` | `tg:Question`, `tg:GraphRagQuestion` | उपयोगकर्ता का प्रश्न |
|
||||
| अन्वेषण | `prov:Entity` | `tg:Exploration` | ज्ञान ग्राफ से प्राप्त किनारे |
|
||||
| फोकस | `prov:Entity` | `tg:Focus` | तर्क के साथ चयनित किनारे |
|
||||
| संश्लेषण | `prov:Entity` | `tg:Synthesis` | अंतिम उत्तर |
|
||||
|
||||
### एजेंट प्रकार
|
||||
| इकाई | पीआरओवी-ओ प्रकार | टीजी प्रकार | विवरण |
|
||||
|--------|-------------|----------|-------------|
|
||||
| प्रश्न | `prov:Activity` | `tg:Question`, `tg:AgentQuestion` | उपयोगकर्ता का प्रश्न |
|
||||
| विश्लेषण | `prov:Entity` | `tg:Analysis` | प्रत्येक सोच/कार्य/अवलोकन चक्र |
|
||||
| निष्कर्ष | `prov:Entity` | `tg:Conclusion` | अंतिम उत्तर |
|
||||
|
||||
### दस्तावेज़ आरएजी प्रकार
|
||||
| इकाई | पीआरओवी-ओ प्रकार | टीजी प्रकार | विवरण |
|
||||
|--------|-------------|----------|-------------|
|
||||
| प्रश्न | `prov:Activity` | `tg:Question`, `tg:DocRagQuestion` | उपयोगकर्ता का प्रश्न |
|
||||
| अन्वेषण | `prov:Entity` | `tg:Exploration` | दस्तावेज़ भंडार से प्राप्त टुकड़े |
|
||||
| संश्लेषण | `prov:Entity` | `tg:Synthesis` | अंतिम उत्तर |
|
||||
|
||||
**ध्यान दें:** दस्तावेज़ आरएजी ग्राफआरएजी के प्रकारों का एक उपसमुच्चय का उपयोग करता है (कोई फोकस चरण नहीं है क्योंकि कोई किनारा चयन/तर्क चरण नहीं है)।
|
||||
|
||||
### प्रश्न उपप्रकार
|
||||
|
||||
सभी प्रश्न इकाइयों में `tg:Question` को एक आधार प्रकार के रूप में साझा किया जाता है, लेकिन पुनर्प्राप्ति तंत्र की पहचान करने के लिए एक विशिष्ट उपप्रकार होता है:
|
||||
|
||||
| उपप्रकार | यूआरआई पैटर्न | तंत्र |
|
||||
|---------|-------------|-----------|
|
||||
| `tg:GraphRagQuestion` | `urn:trustgraph:question:{uuid}` | ज्ञान ग्राफ आरएजी |
|
||||
| `tg:DocRagQuestion` | `urn:trustgraph:docrag:{uuid}` | दस्तावेज़/टुकड़ा आरएजी |
|
||||
| `tg:AgentQuestion` | `urn:trustgraph:agent:{uuid}` | रीएक्ट एजेंट |
|
||||
|
||||
यह सभी प्रश्नों को `tg:Question` के माध्यम से क्वेरी करने की अनुमति देता है, जबकि उपप्रकार के माध्यम से विशिष्ट तंत्र द्वारा फ़िल्टर किया जा सकता है।
|
||||
|
||||
## उत्पत्ति मॉडल
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:agent:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis1 (urn:trustgraph:agent:{uuid}/i1)
|
||||
│
|
||||
│ tg:thought = "I need to query the knowledge base..."
|
||||
│ tg:action = "knowledge-query"
|
||||
│ tg:arguments = {"question": "..."}
|
||||
│ tg:observation = "Result from tool..."
|
||||
│ rdf:type = prov:Entity, tg:Analysis
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis2 (urn:trustgraph:agent:{uuid}/i2)
|
||||
│ ...
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Conclusion (urn:trustgraph:agent:{uuid}/final)
|
||||
│
|
||||
│ tg:answer = "The final response..."
|
||||
│ rdf:type = prov:Entity, tg:Conclusion
|
||||
```
|
||||
|
||||
### दस्तावेज़ आरएजी उत्पत्ति मॉडल
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:docrag:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasGeneratedBy
|
||||
│
|
||||
Exploration (urn:trustgraph:docrag:{uuid}/exploration)
|
||||
│
|
||||
│ tg:chunkCount = 5
|
||||
│ tg:selectedChunk = "chunk-id-1"
|
||||
│ tg:selectedChunk = "chunk-id-2"
|
||||
│ ...
|
||||
│ rdf:type = prov:Entity, tg:Exploration
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Synthesis (urn:trustgraph:docrag:{uuid}/synthesis)
|
||||
│
|
||||
│ tg:content = "The synthesized answer..."
|
||||
│ rdf:type = prov:Entity, tg:Synthesis
|
||||
```
|
||||
|
||||
## आवश्यक परिवर्तन
|
||||
|
||||
### 1. स्कीमा परिवर्तन
|
||||
|
||||
**फ़ाइल:** `trustgraph-base/trustgraph/schema/services/agent.py`
|
||||
|
||||
`AgentRequest` में `session_id` और `collection` फ़ील्ड जोड़ें:
|
||||
```python
|
||||
@dataclass
|
||||
class AgentRequest:
|
||||
question: str = ""
|
||||
state: str = ""
|
||||
group: list[str] | None = None
|
||||
history: list[AgentStep] = field(default_factory=list)
|
||||
user: str = ""
|
||||
collection: str = "default" # NEW: Collection for provenance traces
|
||||
streaming: bool = False
|
||||
session_id: str = "" # NEW: For provenance tracking across iterations
|
||||
```
|
||||
|
||||
**फ़ाइल:** `trustgraph-base/trustgraph/messaging/translators/agent.py`
|
||||
|
||||
अनुवादक को `session_id` और `collection` को `to_pulsar()` और `from_pulsar()` दोनों में संभालने के लिए अपडेट करें।
|
||||
|
||||
### 2. एजेंट सेवा में "एक्सप्लेनेबिलिटी" उत्पादक जोड़ें
|
||||
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/agent/react/service.py`
|
||||
|
||||
एक "एक्सप्लेनेबिलिटी" उत्पादक को पंजीकृत करें (ग्राफआरएजी के समान पैटर्न):
|
||||
```python
|
||||
from ... base import ProducerSpec
|
||||
from ... schema import Triples
|
||||
|
||||
# In __init__:
|
||||
self.register_specification(
|
||||
ProducerSpec(
|
||||
name = "explainability",
|
||||
schema = Triples,
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### 3. उत्पत्ति त्रिक निर्माण
|
||||
|
||||
**फ़ाइल:** `trustgraph-base/trustgraph/provenance/agent.py`
|
||||
|
||||
सहायक फ़ंक्शन बनाएँ (ग्राफ़आरएजी के `question_triples`, `exploration_triples`, आदि के समान):
|
||||
```python
|
||||
def agent_session_triples(session_uri, query, timestamp):
|
||||
"""Generate triples for agent Question."""
|
||||
return [
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=PROV_ACTIVITY),
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=TG_QUESTION),
|
||||
Triple(s=session_uri, p=TG_QUERY, o=query),
|
||||
Triple(s=session_uri, p=PROV_STARTED_AT_TIME, o=timestamp),
|
||||
]
|
||||
|
||||
def agent_iteration_triples(iteration_uri, parent_uri, thought, action, arguments, observation):
|
||||
"""Generate triples for one Analysis step."""
|
||||
return [
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=TG_ANALYSIS),
|
||||
Triple(s=iteration_uri, p=TG_THOUGHT, o=thought),
|
||||
Triple(s=iteration_uri, p=TG_ACTION, o=action),
|
||||
Triple(s=iteration_uri, p=TG_ARGUMENTS, o=json.dumps(arguments)),
|
||||
Triple(s=iteration_uri, p=TG_OBSERVATION, o=observation),
|
||||
Triple(s=iteration_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
|
||||
def agent_final_triples(final_uri, parent_uri, answer):
|
||||
"""Generate triples for Conclusion."""
|
||||
return [
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=TG_CONCLUSION),
|
||||
Triple(s=final_uri, p=TG_ANSWER, o=answer),
|
||||
Triple(s=final_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
```
|
||||
|
||||
### 4. प्रकार की परिभाषाएँ
|
||||
|
||||
**फ़ाइल:** `trustgraph-base/trustgraph/provenance/namespaces.py`
|
||||
|
||||
व्याख्यात्मकता इकाई प्रकार और एजेंट विधेयकों को जोड़ें:
|
||||
```python
|
||||
# Explainability entity types (used by both GraphRAG and Agent)
|
||||
TG_QUESTION = TG + "Question"
|
||||
TG_EXPLORATION = TG + "Exploration"
|
||||
TG_FOCUS = TG + "Focus"
|
||||
TG_SYNTHESIS = TG + "Synthesis"
|
||||
TG_ANALYSIS = TG + "Analysis"
|
||||
TG_CONCLUSION = TG + "Conclusion"
|
||||
|
||||
# Agent predicates
|
||||
TG_THOUGHT = TG + "thought"
|
||||
TG_ACTION = TG + "action"
|
||||
TG_ARGUMENTS = TG + "arguments"
|
||||
TG_OBSERVATION = TG + "observation"
|
||||
TG_ANSWER = TG + "answer"
|
||||
```
|
||||
|
||||
## संशोधित फ़ाइलें
|
||||
|
||||
| फ़ाइल | परिवर्तन |
|
||||
|------|--------|
|
||||
| `trustgraph-base/trustgraph/schema/services/agent.py` | AgentRequest में session_id और collection जोड़ें |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/agent.py` | नए फ़ील्ड के लिए ट्रांसलेटर को अपडेट करें |
|
||||
| `trustgraph-base/trustgraph/provenance/namespaces.py` | एंटिटी प्रकार, एजेंट प्रेडिकेट और Document RAG प्रेडिकेट जोड़ें |
|
||||
| `trustgraph-base/trustgraph/provenance/triples.py` | GraphRAG ट्रिपल बिल्डरों में TG प्रकार जोड़ें, Document RAG ट्रिपल बिल्डर जोड़ें |
|
||||
| `trustgraph-base/trustgraph/provenance/uris.py` | Document RAG URI जनरेटर जोड़ें |
|
||||
| `trustgraph-base/trustgraph/provenance/__init__.py` | नए प्रकार, प्रेडिकेट और Document RAG फ़ंक्शन निर्यात करें |
|
||||
| `trustgraph-base/trustgraph/schema/services/retrieval.py` | DocumentRagResponse में explain_id और explain_graph जोड़ें |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/retrieval.py` | व्याख्यात्मक फ़ील्ड के लिए DocumentRagResponseTranslator को अपडेट करें |
|
||||
| `trustgraph-flow/trustgraph/agent/react/service.py` | व्याख्यात्मक उत्पादक + रिकॉर्डिंग लॉजिक जोड़ें |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` | व्याख्यात्मक कॉलबैक जोड़ें और प्रोवेनेंस ट्रिपल उत्सर्जित करें |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` | व्याख्यात्मक उत्पादक जोड़ें और कॉलबैक को कनेक्ट करें |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | एजेंट ट्रेस प्रकारों को संभालें |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | GraphRAG के साथ एजेंट सत्रों को सूचीबद्ध करें |
|
||||
|
||||
## बनाई गई फ़ाइलें
|
||||
|
||||
| फ़ाइल | उद्देश्य |
|
||||
|------|---------|
|
||||
| `trustgraph-base/trustgraph/provenance/agent.py` | एजेंट-विशिष्ट ट्रिपल जनरेटर |
|
||||
|
||||
## CLI अपडेट
|
||||
|
||||
**पहचान:** GraphRAG और Agent Questions दोनों में `tg:Question` प्रकार होता है। निम्नलिखित द्वारा पहचाना जाता है:
|
||||
1. URI पैटर्न: `urn:trustgraph:agent:` बनाम `urn:trustgraph:question:`
|
||||
2. व्युत्पन्न एंटिटीज: `tg:Analysis` (एजेंट) बनाम `tg:Exploration` (GraphRAG)
|
||||
|
||||
**`list_explain_traces.py`:**
|
||||
टाइप कॉलम दिखाता है (एजेंट बनाम GraphRAG)
|
||||
|
||||
**`show_explain_trace.py`:**
|
||||
स्वचालित रूप से ट्रेस प्रकार का पता लगाता है
|
||||
एजेंट रेंडरिंग दिखाता है: प्रश्न → विश्लेषण चरण(s) → निष्कर्ष
|
||||
|
||||
## पिछली अनुकूलता
|
||||
|
||||
`session_id` डिफ़ॉल्ट रूप से `""` होता है - पुराने अनुरोध काम करते हैं, लेकिन उनमें प्रोवेनेंस नहीं होगा
|
||||
`collection` डिफ़ॉल्ट रूप से `"default"` होता है - उचित बैकअप
|
||||
CLI दोनों ट्रेस प्रकारों को आसानी से संभालता है
|
||||
|
||||
## सत्यापन
|
||||
|
||||
```bash
|
||||
# Run an agent query
|
||||
tg-invoke-agent -q "What is the capital of France?"
|
||||
|
||||
# List traces (should show agent sessions with Type column)
|
||||
tg-list-explain-traces -U trustgraph -C default
|
||||
|
||||
# Show agent trace
|
||||
tg-show-explain-trace "urn:trustgraph:agent:xxx"
|
||||
```
|
||||
|
||||
## भविष्य की योजनाएं (इस पुल अनुरोध में नहीं)
|
||||
|
||||
डीएजी निर्भरताएँ (जब विश्लेषण एन, पिछले कई विश्लेषणों के परिणामों का उपयोग करता है)
|
||||
टूल-विशिष्ट उत्पत्ति लिंकिंग (नॉलेजक्वेरी → इसका ग्राफआरएजी ट्रेस)
|
||||
स्ट्रीमिंग उत्पत्ति उत्सर्जन (जैसे-जैसे उत्पन्न होता है, अंत में बैच न करें)
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Agent Explainability: Provenance Recording"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Agent Explainability: Provenance Recording
|
||||
|
||||
## Overview
|
||||
|
|
|
|||
280
docs/tech-specs/agent-explainability.pt.md
Normal file
280
docs/tech-specs/agent-explainability.pt.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Explicabilidade do Agente: Registro de Proveniência"
|
||||
parent: "Portuguese (Beta)"
|
||||
---
|
||||
|
||||
# Explicabilidade do Agente: Registro de Proveniência
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Adicionar o registro de proveniência ao loop do agente React para que as sessões do agente possam ser rastreadas e depuradas usando a mesma infraestrutura de explicabilidade do GraphRAG.
|
||||
|
||||
**Decisões de Design:**
|
||||
- Escrever em `urn:graph:retrieval` (grafo de explicabilidade genérico)
|
||||
- Cadeia de dependência linear por enquanto (análise N → foiDerivadoDe → análise N-1)
|
||||
- As ferramentas são caixas pretas (registrar apenas entrada/saída)
|
||||
- Suporte a DAG (Directed Acyclic Graph - Grafo Acíclico Direcionado) adiado para uma iteração futura
|
||||
|
||||
## Tipos de Entidade
|
||||
|
||||
Tanto o GraphRAG quanto o Agent usam PROV-O como a ontologia base, com subtipos específicos do TrustGraph:
|
||||
|
||||
### Tipos do GraphRAG
|
||||
| Entidade | Tipo PROV-O | Tipos TG | Descrição |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Pergunta | `prov:Activity` | `tg:Question`, `tg:GraphRagQuestion` | A consulta do usuário |
|
||||
| Exploração | `prov:Entity` | `tg:Exploration` | Arestas recuperadas do grafo de conhecimento |
|
||||
| Foco | `prov:Entity` | `tg:Focus` | Arestas selecionadas com raciocínio |
|
||||
| Síntese | `prov:Entity` | `tg:Synthesis` | Resposta final |
|
||||
|
||||
### Tipos do Agente
|
||||
| Entidade | Tipo PROV-O | Tipos TG | Descrição |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Pergunta | `prov:Activity` | `tg:Question`, `tg:AgentQuestion` | A consulta do usuário |
|
||||
| Análise | `prov:Entity` | `tg:Analysis` | Cada ciclo de pensar/agir/observar |
|
||||
| Conclusão | `prov:Entity` | `tg:Conclusion` | Resposta final |
|
||||
|
||||
### Tipos do Document RAG
|
||||
| Entidade | Tipo PROV-O | Tipos TG | Descrição |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Pergunta | `prov:Activity` | `tg:Question`, `tg:DocRagQuestion` | A consulta do usuário |
|
||||
| Exploração | `prov:Entity` | `tg:Exploration` | Trechos recuperados do armazenamento de documentos |
|
||||
| Síntese | `prov:Entity` | `tg:Synthesis` | Resposta final |
|
||||
|
||||
**Observação:** O Document RAG usa um subconjunto dos tipos do GraphRAG (sem a etapa de Foco, pois não há seleção/raciocínio de arestas).
|
||||
|
||||
### Subtipos de Pergunta
|
||||
|
||||
Todas as entidades de Pergunta compartilham `tg:Question` como um tipo base, mas têm um subtipo específico para identificar o mecanismo de recuperação:
|
||||
|
||||
| Subtipo | Padrão URI | Mecanismo |
|
||||
|---------|-------------|-----------|
|
||||
| `tg:GraphRagQuestion` | `urn:trustgraph:question:{uuid}` | RAG de grafo de conhecimento |
|
||||
| `tg:DocRagQuestion` | `urn:trustgraph:docrag:{uuid}` | RAG de documento/trecho |
|
||||
| `tg:AgentQuestion` | `urn:trustgraph:agent:{uuid}` | Agente ReAct |
|
||||
|
||||
Isso permite consultar todas as perguntas via `tg:Question`, filtrando por mecanismo específico através do subtipo.
|
||||
|
||||
## Modelo de Proveniência
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:agent:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis1 (urn:trustgraph:agent:{uuid}/i1)
|
||||
│
|
||||
│ tg:thought = "I need to query the knowledge base..."
|
||||
│ tg:action = "knowledge-query"
|
||||
│ tg:arguments = {"question": "..."}
|
||||
│ tg:observation = "Result from tool..."
|
||||
│ rdf:type = prov:Entity, tg:Analysis
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis2 (urn:trustgraph:agent:{uuid}/i2)
|
||||
│ ...
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Conclusion (urn:trustgraph:agent:{uuid}/final)
|
||||
│
|
||||
│ tg:answer = "The final response..."
|
||||
│ rdf:type = prov:Entity, tg:Conclusion
|
||||
```
|
||||
|
||||
### Modelo de Proveniência de Documentos RAG
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:docrag:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasGeneratedBy
|
||||
│
|
||||
Exploration (urn:trustgraph:docrag:{uuid}/exploration)
|
||||
│
|
||||
│ tg:chunkCount = 5
|
||||
│ tg:selectedChunk = "chunk-id-1"
|
||||
│ tg:selectedChunk = "chunk-id-2"
|
||||
│ ...
|
||||
│ rdf:type = prov:Entity, tg:Exploration
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Synthesis (urn:trustgraph:docrag:{uuid}/synthesis)
|
||||
│
|
||||
│ tg:content = "The synthesized answer..."
|
||||
│ rdf:type = prov:Entity, tg:Synthesis
|
||||
```
|
||||
|
||||
## Alterações Necessárias
|
||||
|
||||
### 1. Alterações no Esquema
|
||||
|
||||
**Arquivo:** `trustgraph-base/trustgraph/schema/services/agent.py`
|
||||
|
||||
Adicionar os campos `session_id` e `collection` a `AgentRequest`:
|
||||
```python
|
||||
@dataclass
|
||||
class AgentRequest:
|
||||
question: str = ""
|
||||
state: str = ""
|
||||
group: list[str] | None = None
|
||||
history: list[AgentStep] = field(default_factory=list)
|
||||
user: str = ""
|
||||
collection: str = "default" # NEW: Collection for provenance traces
|
||||
streaming: bool = False
|
||||
session_id: str = "" # NEW: For provenance tracking across iterations
|
||||
```
|
||||
|
||||
**Arquivo:** `trustgraph-base/trustgraph/messaging/translators/agent.py`
|
||||
|
||||
Atualizar o tradutor para lidar com `session_id` e `collection` tanto em `to_pulsar()` quanto em `from_pulsar()`.
|
||||
|
||||
### 2. Adicionar Produtor de Explicabilidade ao Serviço de Agente
|
||||
|
||||
**Arquivo:** `trustgraph-flow/trustgraph/agent/react/service.py`
|
||||
|
||||
Registrar um "produtor de explicabilidade" (mesmo padrão do GraphRAG):
|
||||
```python
|
||||
from ... base import ProducerSpec
|
||||
from ... schema import Triples
|
||||
|
||||
# In __init__:
|
||||
self.register_specification(
|
||||
ProducerSpec(
|
||||
name = "explainability",
|
||||
schema = Triples,
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### 3. Geração de Triplas de Proveniência
|
||||
|
||||
**Arquivo:** `trustgraph-base/trustgraph/provenance/agent.py`
|
||||
|
||||
Crie funções auxiliares (semelhantes a `question_triples`, `exploration_triples`, etc. do GraphRAG):
|
||||
```python
|
||||
def agent_session_triples(session_uri, query, timestamp):
|
||||
"""Generate triples for agent Question."""
|
||||
return [
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=PROV_ACTIVITY),
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=TG_QUESTION),
|
||||
Triple(s=session_uri, p=TG_QUERY, o=query),
|
||||
Triple(s=session_uri, p=PROV_STARTED_AT_TIME, o=timestamp),
|
||||
]
|
||||
|
||||
def agent_iteration_triples(iteration_uri, parent_uri, thought, action, arguments, observation):
|
||||
"""Generate triples for one Analysis step."""
|
||||
return [
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=TG_ANALYSIS),
|
||||
Triple(s=iteration_uri, p=TG_THOUGHT, o=thought),
|
||||
Triple(s=iteration_uri, p=TG_ACTION, o=action),
|
||||
Triple(s=iteration_uri, p=TG_ARGUMENTS, o=json.dumps(arguments)),
|
||||
Triple(s=iteration_uri, p=TG_OBSERVATION, o=observation),
|
||||
Triple(s=iteration_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
|
||||
def agent_final_triples(final_uri, parent_uri, answer):
|
||||
"""Generate triples for Conclusion."""
|
||||
return [
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=TG_CONCLUSION),
|
||||
Triple(s=final_uri, p=TG_ANSWER, o=answer),
|
||||
Triple(s=final_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
```
|
||||
|
||||
### 4. Definições de Tipo
|
||||
|
||||
**Arquivo:** `trustgraph-base/trustgraph/provenance/namespaces.py`
|
||||
|
||||
Adicionar tipos de entidade de explicabilidade e predicados de agente:
|
||||
```python
|
||||
# Explainability entity types (used by both GraphRAG and Agent)
|
||||
TG_QUESTION = TG + "Question"
|
||||
TG_EXPLORATION = TG + "Exploration"
|
||||
TG_FOCUS = TG + "Focus"
|
||||
TG_SYNTHESIS = TG + "Synthesis"
|
||||
TG_ANALYSIS = TG + "Analysis"
|
||||
TG_CONCLUSION = TG + "Conclusion"
|
||||
|
||||
# Agent predicates
|
||||
TG_THOUGHT = TG + "thought"
|
||||
TG_ACTION = TG + "action"
|
||||
TG_ARGUMENTS = TG + "arguments"
|
||||
TG_OBSERVATION = TG + "observation"
|
||||
TG_ANSWER = TG + "answer"
|
||||
```
|
||||
|
||||
## Arquivos Modificados
|
||||
|
||||
| Arquivo | Alteração |
|
||||
|------|--------|
|
||||
| `trustgraph-base/trustgraph/schema/services/agent.py` | Adiciona session_id e collection a AgentRequest |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/agent.py` | Atualiza o tradutor para novos campos |
|
||||
| `trustgraph-base/trustgraph/provenance/namespaces.py` | Adiciona tipos de entidade, predicados de agente e predicados Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/triples.py` | Adiciona tipos TG aos construtores de triplas GraphRAG, adiciona construtores de triplas Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/uris.py` | Adiciona geradores de URI Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/__init__.py` | Exporta novos tipos, predicados e funções Document RAG |
|
||||
| `trustgraph-base/trustgraph/schema/services/retrieval.py` | Adiciona explain_id e explain_graph a DocumentRagResponse |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/retrieval.py` | Atualiza DocumentRagResponseTranslator para campos de explicabilidade |
|
||||
| `trustgraph-flow/trustgraph/agent/react/service.py` | Adiciona lógica de produção e gravação de explicabilidade |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` | Adiciona callback de explicabilidade e emite triplas de procedência |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` | Adiciona produtor de explicabilidade e conecta o callback |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | Lida com tipos de rastreamento de agente |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | Lista sessões de agente junto com GraphRAG |
|
||||
|
||||
## Arquivos Criados
|
||||
|
||||
| Arquivo | Propósito |
|
||||
|------|---------|
|
||||
| `trustgraph-base/trustgraph/provenance/agent.py` | Geradores de triplas específicos para agente |
|
||||
|
||||
## Atualizações da CLI
|
||||
|
||||
**Detecção:** Tanto GraphRAG quanto Agent Questions têm o tipo `tg:Question`. Distinguido por:
|
||||
1. Padrão de URI: `urn:trustgraph:agent:` vs `urn:trustgraph:question:`
|
||||
2. Entidades derivadas: `tg:Analysis` (agente) vs `tg:Exploration` (GraphRAG)
|
||||
|
||||
**`list_explain_traces.py`:**
|
||||
- Mostra a coluna Tipo (Agente vs GraphRAG)
|
||||
|
||||
**`show_explain_trace.py`:**
|
||||
- Detecta automaticamente o tipo de rastreamento
|
||||
- A renderização do agente mostra: Pergunta → Etapa(s) de análise → Conclusão
|
||||
|
||||
## Compatibilidade com versões anteriores
|
||||
|
||||
- `session_id` padrão é `""` - solicitações antigas funcionam, mas não terão procedência
|
||||
- `collection` padrão é `"default"` - fallback razoável
|
||||
- A CLI lida graciosamente com ambos os tipos de rastreamento
|
||||
|
||||
## Verificação
|
||||
|
||||
```bash
|
||||
# Run an agent query
|
||||
tg-invoke-agent -q "What is the capital of France?"
|
||||
|
||||
# List traces (should show agent sessions with Type column)
|
||||
tg-list-explain-traces -U trustgraph -C default
|
||||
|
||||
# Show agent trace
|
||||
tg-show-explain-trace "urn:trustgraph:agent:xxx"
|
||||
```
|
||||
|
||||
## Trabalhos Futuros (Não Neste PR)
|
||||
|
||||
- Dependências de DAG (quando a análise N usa resultados de várias análises anteriores)
|
||||
- Vinculação de rastreabilidade específica da ferramenta (KnowledgeQuery → seu rastreamento GraphRAG)
|
||||
- Emissão de rastreabilidade em fluxo (emitir continuamente, não em lote no final)
|
||||
280
docs/tech-specs/agent-explainability.ru.md
Normal file
280
docs/tech-specs/agent-explainability.ru.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Объяснимость работы агента: Регистрация происхождения"
|
||||
parent: "Russian (Beta)"
|
||||
---
|
||||
|
||||
# Объяснимость работы агента: Регистрация происхождения
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Обзор
|
||||
|
||||
Добавьте регистрацию происхождения в цикл работы агента React, чтобы сеансы работы агента можно было отслеживать и отлаживать с использованием той же инфраструктуры объяснимости, что и в GraphRAG.
|
||||
|
||||
**Принятые решения:**
|
||||
Запись в `urn:graph:retrieval` (общий граф объяснимости)
|
||||
Линейная цепочка зависимостей на данный момент (анализ N → был получен из → анализ N-1)
|
||||
Инструменты являются непрозрачными "черными ящиками" (записывайте только входные и выходные данные)
|
||||
Поддержка DAG отложена до будущей итерации
|
||||
|
||||
## Типы сущностей
|
||||
|
||||
И GraphRAG, и Agent используют PROV-O в качестве базовой онтологии с подтипами, специфичными для TrustGraph:
|
||||
|
||||
### Типы GraphRAG
|
||||
| Сущность | Тип PROV-O | Типы TG | Описание |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Вопрос | `prov:Activity` | `tg:Question`, `tg:GraphRagQuestion` | Запрос пользователя |
|
||||
| Исследование | `prov:Entity` | `tg:Exploration` | Ряды, извлеченные из графа знаний |
|
||||
| Фокус | `prov:Entity` | `tg:Focus` | Выбранные ряды с обоснованием |
|
||||
| Синтез | `prov:Entity` | `tg:Synthesis` | Окончательный ответ |
|
||||
|
||||
### Типы Agent
|
||||
| Сущность | Тип PROV-O | Типы TG | Описание |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Вопрос | `prov:Activity` | `tg:Question`, `tg:AgentQuestion` | Запрос пользователя |
|
||||
| Анализ | `prov:Entity` | `tg:Analysis` | Каждый цикл "думай/действуй/наблюдай" |
|
||||
| Вывод | `prov:Entity` | `tg:Conclusion` | Окончательный ответ |
|
||||
|
||||
### Типы Document RAG
|
||||
| Сущность | Тип PROV-O | Типы TG | Описание |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Вопрос | `prov:Activity` | `tg:Question`, `tg:DocRagQuestion` | Запрос пользователя |
|
||||
| Исследование | `prov:Entity` | `tg:Exploration` | Части, извлеченные из хранилища документов |
|
||||
| Синтез | `prov:Entity` | `tg:Synthesis` | Окончательный ответ |
|
||||
|
||||
**Примечание:** Document RAG использует подмножество типов GraphRAG (нет этапа "Фокус", поскольку нет этапа выбора/обоснования ребер).
|
||||
|
||||
### Подтипы вопросов
|
||||
|
||||
Все сущности "Вопрос" имеют `tg:Question` в качестве базового типа, но имеют определенный подтип для идентификации механизма извлечения:
|
||||
|
||||
| Подтип | Шаблон URI | Механизм |
|
||||
|---------|-------------|-----------|
|
||||
| `tg:GraphRagQuestion` | `urn:trustgraph:question:{uuid}` | RAG на основе графа знаний |
|
||||
| `tg:DocRagQuestion` | `urn:trustgraph:docrag:{uuid}` | RAG на основе документов/частей |
|
||||
| `tg:AgentQuestion` | `urn:trustgraph:agent:{uuid}` | Агент ReAct |
|
||||
|
||||
Это позволяет запрашивать все вопросы через `tg:Question`, одновременно фильтруя по конкретному механизму с помощью подтипа.
|
||||
|
||||
## Модель происхождения
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:agent:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis1 (urn:trustgraph:agent:{uuid}/i1)
|
||||
│
|
||||
│ tg:thought = "I need to query the knowledge base..."
|
||||
│ tg:action = "knowledge-query"
|
||||
│ tg:arguments = {"question": "..."}
|
||||
│ tg:observation = "Result from tool..."
|
||||
│ rdf:type = prov:Entity, tg:Analysis
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis2 (urn:trustgraph:agent:{uuid}/i2)
|
||||
│ ...
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Conclusion (urn:trustgraph:agent:{uuid}/final)
|
||||
│
|
||||
│ tg:answer = "The final response..."
|
||||
│ rdf:type = prov:Entity, tg:Conclusion
|
||||
```
|
||||
|
||||
### Модель происхождения документов RAG
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:docrag:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasGeneratedBy
|
||||
│
|
||||
Exploration (urn:trustgraph:docrag:{uuid}/exploration)
|
||||
│
|
||||
│ tg:chunkCount = 5
|
||||
│ tg:selectedChunk = "chunk-id-1"
|
||||
│ tg:selectedChunk = "chunk-id-2"
|
||||
│ ...
|
||||
│ rdf:type = prov:Entity, tg:Exploration
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Synthesis (urn:trustgraph:docrag:{uuid}/synthesis)
|
||||
│
|
||||
│ tg:content = "The synthesized answer..."
|
||||
│ rdf:type = prov:Entity, tg:Synthesis
|
||||
```
|
||||
|
||||
## Необходимые изменения
|
||||
|
||||
### 1. Изменения схемы
|
||||
|
||||
**Файл:** `trustgraph-base/trustgraph/schema/services/agent.py`
|
||||
|
||||
Добавить поля `session_id` и `collection` в `AgentRequest`:
|
||||
```python
|
||||
@dataclass
|
||||
class AgentRequest:
|
||||
question: str = ""
|
||||
state: str = ""
|
||||
group: list[str] | None = None
|
||||
history: list[AgentStep] = field(default_factory=list)
|
||||
user: str = ""
|
||||
collection: str = "default" # NEW: Collection for provenance traces
|
||||
streaming: bool = False
|
||||
session_id: str = "" # NEW: For provenance tracking across iterations
|
||||
```
|
||||
|
||||
**Файл:** `trustgraph-base/trustgraph/messaging/translators/agent.py`
|
||||
|
||||
Обновить переводчик для обработки `session_id` и `collection` как в `to_pulsar()`, так и в `from_pulsar()`.
|
||||
|
||||
### 2. Добавить компонент "Explainability Producer" в сервис Agent
|
||||
|
||||
**Файл:** `trustgraph-flow/trustgraph/agent/react/service.py`
|
||||
|
||||
Зарегистрировать компонент "explainability" (в соответствии с тем же шаблоном, что и GraphRAG):
|
||||
```python
|
||||
from ... base import ProducerSpec
|
||||
from ... schema import Triples
|
||||
|
||||
# In __init__:
|
||||
self.register_specification(
|
||||
ProducerSpec(
|
||||
name = "explainability",
|
||||
schema = Triples,
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### 3. Генерация триплетов происхождения
|
||||
|
||||
**Файл:** `trustgraph-base/trustgraph/provenance/agent.py`
|
||||
|
||||
Создайте вспомогательные функции (подобные `question_triples`, `exploration_triples` и т.д. в GraphRAG):
|
||||
```python
|
||||
def agent_session_triples(session_uri, query, timestamp):
|
||||
"""Generate triples for agent Question."""
|
||||
return [
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=PROV_ACTIVITY),
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=TG_QUESTION),
|
||||
Triple(s=session_uri, p=TG_QUERY, o=query),
|
||||
Triple(s=session_uri, p=PROV_STARTED_AT_TIME, o=timestamp),
|
||||
]
|
||||
|
||||
def agent_iteration_triples(iteration_uri, parent_uri, thought, action, arguments, observation):
|
||||
"""Generate triples for one Analysis step."""
|
||||
return [
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=TG_ANALYSIS),
|
||||
Triple(s=iteration_uri, p=TG_THOUGHT, o=thought),
|
||||
Triple(s=iteration_uri, p=TG_ACTION, o=action),
|
||||
Triple(s=iteration_uri, p=TG_ARGUMENTS, o=json.dumps(arguments)),
|
||||
Triple(s=iteration_uri, p=TG_OBSERVATION, o=observation),
|
||||
Triple(s=iteration_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
|
||||
def agent_final_triples(final_uri, parent_uri, answer):
|
||||
"""Generate triples for Conclusion."""
|
||||
return [
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=TG_CONCLUSION),
|
||||
Triple(s=final_uri, p=TG_ANSWER, o=answer),
|
||||
Triple(s=final_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
```
|
||||
|
||||
### 4. Определения типов
|
||||
|
||||
**Файл:** `trustgraph-base/trustgraph/provenance/namespaces.py`
|
||||
|
||||
Добавить типы сущностей, обеспечивающих объяснимость, и предикаты агентов:
|
||||
```python
|
||||
# Explainability entity types (used by both GraphRAG and Agent)
|
||||
TG_QUESTION = TG + "Question"
|
||||
TG_EXPLORATION = TG + "Exploration"
|
||||
TG_FOCUS = TG + "Focus"
|
||||
TG_SYNTHESIS = TG + "Synthesis"
|
||||
TG_ANALYSIS = TG + "Analysis"
|
||||
TG_CONCLUSION = TG + "Conclusion"
|
||||
|
||||
# Agent predicates
|
||||
TG_THOUGHT = TG + "thought"
|
||||
TG_ACTION = TG + "action"
|
||||
TG_ARGUMENTS = TG + "arguments"
|
||||
TG_OBSERVATION = TG + "observation"
|
||||
TG_ANSWER = TG + "answer"
|
||||
```
|
||||
|
||||
## Измененные файлы
|
||||
|
||||
| Файл | Изменение |
|
||||
|------|--------|
|
||||
| `trustgraph-base/trustgraph/schema/services/agent.py` | Добавлены session_id и collection в AgentRequest |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/agent.py` | Обновлен переводчик для новых полей |
|
||||
| `trustgraph-base/trustgraph/provenance/namespaces.py` | Добавлены типы сущностей, предикаты агента и предикаты Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/triples.py` | Добавлены типы TG для конструкторов троек GraphRAG, добавлены конструкторы троек Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/uris.py` | Добавлены генераторы URI для Document RAG |
|
||||
| `trustgraph-base/trustgraph/provenance/__init__.py` | Экспортированы новые типы, предикаты и функции Document RAG |
|
||||
| `trustgraph-base/trustgraph/schema/services/retrieval.py` | Добавлены explain_id и explain_graph в DocumentRagResponse |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/retrieval.py` | Обновлен DocumentRagResponseTranslator для полей, связанных с объяснением |
|
||||
| `trustgraph-flow/trustgraph/agent/react/service.py` | Добавлена логика создания и записи информации о объяснении |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` | Добавлен колбэк для информации о объяснении и выводятся тройки, содержащие информацию о происхождении |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` | Добавлен генератор информации о объяснении и подключен колбэк |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | Обработка типов трассировки агента |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | Отображение сессий агента вместе с GraphRAG |
|
||||
|
||||
## Созданные файлы
|
||||
|
||||
| Файл | Назначение |
|
||||
|------|---------|
|
||||
| `trustgraph-base/trustgraph/provenance/agent.py` | Генераторы троек, специфичные для агента |
|
||||
|
||||
## Обновления CLI
|
||||
|
||||
**Обнаружение:** И GraphRAG, и вопросы агента имеют тип `tg:Question`. Отличаются следующим:
|
||||
1. Шаблон URI: `urn:trustgraph:agent:` против `urn:trustgraph:question:`
|
||||
2. Выводимые сущности: `tg:Analysis` (агент) против `tg:Exploration` (GraphRAG)
|
||||
|
||||
**`list_explain_traces.py`:**
|
||||
Отображает столбец "Тип" (Агент против GraphRAG)
|
||||
|
||||
**`show_explain_trace.py`:**
|
||||
Автоматически определяет тип трассировки
|
||||
Отображение информации об агенте: Вопрос → Шаги анализа → Вывод
|
||||
|
||||
## Обратная совместимость
|
||||
|
||||
`session_id` по умолчанию равно `""` - старые запросы работают, но не будут содержать информацию о происхождении
|
||||
`collection` по умолчанию равно `"default"` - разумная альтернатива
|
||||
CLI корректно обрабатывает оба типа трассировки
|
||||
|
||||
## Проверка
|
||||
|
||||
```bash
|
||||
# Run an agent query
|
||||
tg-invoke-agent -q "What is the capital of France?"
|
||||
|
||||
# List traces (should show agent sessions with Type column)
|
||||
tg-list-explain-traces -U trustgraph -C default
|
||||
|
||||
# Show agent trace
|
||||
tg-show-explain-trace "urn:trustgraph:agent:xxx"
|
||||
```
|
||||
|
||||
## Будущие задачи (не входят в этот PR)
|
||||
|
||||
Зависимости DAG (когда анализ N использует результаты нескольких предыдущих анализов)
|
||||
Связь с конкретными инструментами (KnowledgeQuery → его трассировка GraphRAG)
|
||||
Потоковая передача метаданных (отправлять по мере выполнения, а не пакетами в конце)
|
||||
280
docs/tech-specs/agent-explainability.sw.md
Normal file
280
docs/tech-specs/agent-explainability.sw.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Ufafanuzi wa Mwakala: Urekodaji wa Asili"
|
||||
parent: "Swahili (Beta)"
|
||||
---
|
||||
|
||||
# Ufafanuzi wa Mwakala: Urekodaji wa Asili
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Muhtasari
|
||||
|
||||
Ongeza urekodaji wa asili kwenye mzunguko wa wakala wa React ili vipindi vya wakala viweze kufuatiliwa na kurekebishwa kwa kutumia miundomino sawa ya ufafanuzi kama GraphRAG.
|
||||
|
||||
**Maamuzi ya Ubunifu:**
|
||||
- Andika kwenye `urn:graph:retrieval` (picha ya ufafanuzi ya jumla)
|
||||
- Mnyororo wa utegemezi wa mstari kwa sasa (uchambuzi N → ilitokana na → uchambuzi N-1)
|
||||
- Zana ni masanduku meusi (rekodi tu ingizo/patto)
|
||||
- Usaidizi wa DAG umeahirishwa hadi toleo la baadaye
|
||||
|
||||
## Aina za Vitambulisho
|
||||
|
||||
GraphRAG na Agent hutumia PROV-O kama ontolojia ya msingi na aina za ziada maalum za TrustGraph:
|
||||
|
||||
### Aina za GraphRAG
|
||||
| Vitambulisho | Aina ya PROV-O | Aina za TG | Maelezo |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Swali | `prov:Activity` | `tg:Question`, `tg:GraphRagQuestion` | Uliza wa mtumiaji |
|
||||
| Uchunguzi | `prov:Entity` | `tg:Exploration` | Edges iliyopatikana kutoka kwenye grafu ya maarifa |
|
||||
| Lengo | `prov:Entity` | `tg:Focus` | Edges iliyochaguliwa na hoja |
|
||||
| Muunganisho | `prov:Entity` | `tg:Synthesis` | Jibu la mwisho |
|
||||
|
||||
### Aina za Wakala
|
||||
| Vitambulisho | Aina ya PROV-O | Aina za TG | Maelezo |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Swali | `prov:Activity` | `tg:Question`, `tg:AgentQuestion` | Uliza wa mtumiaji |
|
||||
| Uchambuzi | `prov:Entity` | `tg:Analysis` | Kila mzunguko wa kufikiria/kutenda/kuona |
|
||||
| Hitimisho | `prov:Entity` | `tg:Conclusion` | Jibu la mwisho |
|
||||
|
||||
### Aina za RAG za Hati
|
||||
| Vitambulisho | Aina ya PROV-O | Aina za TG | Maelezo |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Swali | `prov:Activity` | `tg:Question`, `tg:DocRagQuestion` | Uliza wa mtumiaji |
|
||||
| Uchunguzi | `prov:Entity` | `tg:Exploration` | Sehemu zilizopatikana kutoka kwenye duka la hati |
|
||||
| Muunganisho | `prov:Entity` | `tg:Synthesis` | Jibu la mwisho |
|
||||
|
||||
**Kumbuka:** RAG ya Hati hutumia sehemu ya aina za GraphRAG (hakuna hatua ya Lengo kwa sababu hakuna awamu ya uteuzi/hoja ya edge).
|
||||
|
||||
### Aina za Ndogo za Swali
|
||||
|
||||
Aina zote za Swali hushiriki `tg:Question` kama aina ya msingi lakini zina aina maalum ili kutambua utaratibu wa urejesho:
|
||||
|
||||
| Aina | Mfumo wa URI | Utaratibu |
|
||||
|---------|-------------|-----------|
|
||||
| `tg:GraphRagQuestion` | `urn:trustgraph:question:{uuid}` | RAG ya grafu ya maarifa |
|
||||
| `tg:DocRagQuestion` | `urn:trustgraph:docrag:{uuid}` | RAG ya hati/sehemu |
|
||||
| `tg:AgentQuestion` | `urn:trustgraph:agent:{uuid}` | Wakala wa ReAct |
|
||||
|
||||
Hii inaruhusu kuuliza maswali yote kupitia `tg:Question` huku ikiwezesha kuchujwa kwa utaratibu maalum kupitia aina.
|
||||
|
||||
## Mfumo wa Asili
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:agent:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis1 (urn:trustgraph:agent:{uuid}/i1)
|
||||
│
|
||||
│ tg:thought = "I need to query the knowledge base..."
|
||||
│ tg:action = "knowledge-query"
|
||||
│ tg:arguments = {"question": "..."}
|
||||
│ tg:observation = "Result from tool..."
|
||||
│ rdf:type = prov:Entity, tg:Analysis
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis2 (urn:trustgraph:agent:{uuid}/i2)
|
||||
│ ...
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Conclusion (urn:trustgraph:agent:{uuid}/final)
|
||||
│
|
||||
│ tg:answer = "The final response..."
|
||||
│ rdf:type = prov:Entity, tg:Conclusion
|
||||
```
|
||||
|
||||
### Mfumo wa Asili ya Hati ya RAG
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:docrag:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasGeneratedBy
|
||||
│
|
||||
Exploration (urn:trustgraph:docrag:{uuid}/exploration)
|
||||
│
|
||||
│ tg:chunkCount = 5
|
||||
│ tg:selectedChunk = "chunk-id-1"
|
||||
│ tg:selectedChunk = "chunk-id-2"
|
||||
│ ...
|
||||
│ rdf:type = prov:Entity, tg:Exploration
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Synthesis (urn:trustgraph:docrag:{uuid}/synthesis)
|
||||
│
|
||||
│ tg:content = "The synthesized answer..."
|
||||
│ rdf:type = prov:Entity, tg:Synthesis
|
||||
```
|
||||
|
||||
## Mabadiliko Yanayohitajika
|
||||
|
||||
### 1. Mabadiliko ya Muundo
|
||||
|
||||
**Faili:** `trustgraph-base/trustgraph/schema/services/agent.py`
|
||||
|
||||
Ongeza sehemu za `session_id` na `collection` kwenye `AgentRequest`:
|
||||
```python
|
||||
@dataclass
|
||||
class AgentRequest:
|
||||
question: str = ""
|
||||
state: str = ""
|
||||
group: list[str] | None = None
|
||||
history: list[AgentStep] = field(default_factory=list)
|
||||
user: str = ""
|
||||
collection: str = "default" # NEW: Collection for provenance traces
|
||||
streaming: bool = False
|
||||
session_id: str = "" # NEW: For provenance tracking across iterations
|
||||
```
|
||||
|
||||
**Faidio:** `trustgraph-base/trustgraph/messaging/translators/agent.py`
|
||||
|
||||
Sasisha mtafsiri ili kushughulikia `session_id` na `collection` katika `to_pulsar()` na `from_pulsar()`.
|
||||
|
||||
### 2. Ongeza Mzalishaji wa Ufafanuzi kwa Huduma ya Wakala
|
||||
|
||||
**Faidio:** `trustgraph-flow/trustgraph/agent/react/service.py`
|
||||
|
||||
Sajili "mzalishaji wa ufafanuzi" (mfumo sawa na GraphRAG):
|
||||
```python
|
||||
from ... base import ProducerSpec
|
||||
from ... schema import Triples
|
||||
|
||||
# In __init__:
|
||||
self.register_specification(
|
||||
ProducerSpec(
|
||||
name = "explainability",
|
||||
schema = Triples,
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### 3. Uzalishaji wa Mfumo wa Asili
|
||||
|
||||
**Faili:** `trustgraph-base/trustgraph/provenance/agent.py`
|
||||
|
||||
Unda kazi za msaada (kama zile za GraphRAG, kama `question_triples`, `exploration_triples`, n.k.):
|
||||
```python
|
||||
def agent_session_triples(session_uri, query, timestamp):
|
||||
"""Generate triples for agent Question."""
|
||||
return [
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=PROV_ACTIVITY),
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=TG_QUESTION),
|
||||
Triple(s=session_uri, p=TG_QUERY, o=query),
|
||||
Triple(s=session_uri, p=PROV_STARTED_AT_TIME, o=timestamp),
|
||||
]
|
||||
|
||||
def agent_iteration_triples(iteration_uri, parent_uri, thought, action, arguments, observation):
|
||||
"""Generate triples for one Analysis step."""
|
||||
return [
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=TG_ANALYSIS),
|
||||
Triple(s=iteration_uri, p=TG_THOUGHT, o=thought),
|
||||
Triple(s=iteration_uri, p=TG_ACTION, o=action),
|
||||
Triple(s=iteration_uri, p=TG_ARGUMENTS, o=json.dumps(arguments)),
|
||||
Triple(s=iteration_uri, p=TG_OBSERVATION, o=observation),
|
||||
Triple(s=iteration_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
|
||||
def agent_final_triples(final_uri, parent_uri, answer):
|
||||
"""Generate triples for Conclusion."""
|
||||
return [
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=TG_CONCLUSION),
|
||||
Triple(s=final_uri, p=TG_ANSWER, o=answer),
|
||||
Triple(s=final_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
```
|
||||
|
||||
### 4. Ufafanuzi wa Aina
|
||||
|
||||
**Faili:** `trustgraph-base/trustgraph/provenance/namespaces.py`
|
||||
|
||||
Ongeza aina za vitu vya uelewaji na sentensi za wakala:
|
||||
```python
|
||||
# Explainability entity types (used by both GraphRAG and Agent)
|
||||
TG_QUESTION = TG + "Question"
|
||||
TG_EXPLORATION = TG + "Exploration"
|
||||
TG_FOCUS = TG + "Focus"
|
||||
TG_SYNTHESIS = TG + "Synthesis"
|
||||
TG_ANALYSIS = TG + "Analysis"
|
||||
TG_CONCLUSION = TG + "Conclusion"
|
||||
|
||||
# Agent predicates
|
||||
TG_THOUGHT = TG + "thought"
|
||||
TG_ACTION = TG + "action"
|
||||
TG_ARGUMENTS = TG + "arguments"
|
||||
TG_OBSERVATION = TG + "observation"
|
||||
TG_ANSWER = TG + "answer"
|
||||
```
|
||||
|
||||
## Faili Yaliyobadilishwa
|
||||
|
||||
| Faili | Mabadiliko |
|
||||
|------|--------|
|
||||
| `trustgraph-base/trustgraph/schema/services/agent.py` | Ongeza `session_id` na `collection` kwenye `AgentRequest` |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/agent.py` | Sasisha `translator` kwa ajili ya sehemu mpya |
|
||||
| `trustgraph-base/trustgraph/provenance/namespaces.py` | Ongeza aina za `entity`, `agent predicates`, na `Document RAG predicates` |
|
||||
| `trustgraph-base/trustgraph/provenance/triples.py` | Ongeza aina za `TG` kwenye `GraphRAG triple builders`, ongeza `Document RAG triple builders` |
|
||||
| `trustgraph-base/trustgraph/provenance/uris.py` | Ongeza `Document RAG URI generators` |
|
||||
| `trustgraph-base/trustgraph/provenance/__init__.py` | Export aina mpya, `predicates`, na `Document RAG functions` |
|
||||
| `trustgraph-base/trustgraph/schema/services/retrieval.py` | Ongeza `explain_id` na `explain_graph` kwenye `DocumentRagResponse` |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/retrieval.py` | Sasisha `DocumentRagResponseTranslator` kwa ajili ya sehemu za `explainability` |
|
||||
| `trustgraph-flow/trustgraph/agent/react/service.py` | Ongeza mzalishaji wa `explainability` + mantiki ya kurekodi |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` | Ongeza `explainability callback` na toa `provenance triples` |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` | Ongeza mzalishaji wa `explainability` na uunganishe `callback` |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | Shirikisha aina za `agent trace` |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | Orodha `agent sessions` pamoja na `GraphRAG` |
|
||||
|
||||
## Faili Zilizoundwa
|
||||
|
||||
| Faili | Madhumuni |
|
||||
|------|---------|
|
||||
| `trustgraph-base/trustgraph/provenance/agent.py` | Wazalishaji wa `triple` maalum kwa `agent` |
|
||||
|
||||
## Mabadiliko ya CLI
|
||||
|
||||
**Kugundua:** Maswali ya `GraphRAG` na `Agent` yana aina ya `tg:Question`. Hutofautishwa na:
|
||||
1. Mfumo wa `URI`: `urn:trustgraph:agent:` dhidi ya `urn:trustgraph:question:`
|
||||
2. Vipengele vilivyotokana: `tg:Analysis` (`agent`) dhidi ya `tg:Exploration` (`GraphRAG`)
|
||||
|
||||
**`list_explain_traces.py`:**
|
||||
- Inaonyesha safu ya Aina (Agent vs GraphRAG)
|
||||
|
||||
**`show_explain_trace.py`:**
|
||||
- Hugundua kiotomatiki aina ya `trace`
|
||||
- Uonyesho wa `agent` unaonyesha: Swali → Hatua za uchambuzi → Hitimisho
|
||||
|
||||
## Utangamano na Mifumo ya Zamani
|
||||
|
||||
- `session_id` huenda kwa `""` - maombi ya zamani hufanya kazi, lakini hayata na `provenance`
|
||||
- `collection` huenda kwa `"default"` - `fallback` inayofaa
|
||||
- CLI hushughulikia aina zote za `trace` kwa utulivu
|
||||
|
||||
## Uthibitisho
|
||||
|
||||
```bash
|
||||
# Run an agent query
|
||||
tg-invoke-agent -q "What is the capital of France?"
|
||||
|
||||
# List traces (should show agent sessions with Type column)
|
||||
tg-list-explain-traces -U trustgraph -C default
|
||||
|
||||
# Show agent trace
|
||||
tg-show-explain-trace "urn:trustgraph:agent:xxx"
|
||||
```
|
||||
|
||||
## Kazi Zinazotarajiwa (Sio Katika Mradi Huyu)
|
||||
|
||||
- Utendakazi wa utegemezi wa DAG (wakati uchambuzi N hutumia matokeo kutoka kwa uchambuzi kadhaa uliopita)
|
||||
- Uunganisho wa utambulisho wa zana maalum (KnowledgeQuery → faili yake ya GraphRAG)
|
||||
- Utumaji wa utambulisho wa mtiririko (tumia kwa wakati, sio kwa wingi mwisho)
|
||||
280
docs/tech-specs/agent-explainability.tr.md
Normal file
280
docs/tech-specs/agent-explainability.tr.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Ajan Açıklanabilirliği: Kaynak Kaydı"
|
||||
parent: "Turkish (Beta)"
|
||||
---
|
||||
|
||||
# Ajan Açıklanabilirliği: Kaynak Kaydı
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Genel Bakış
|
||||
|
||||
Ajan oturumlarının izlenebilmesi ve GraphRAG ile aynı açıklanabilirlik altyapısı kullanılarak hata ayıklanabilmesi için, React ajan döngüsüne kaynak kaydı ekleyin.
|
||||
|
||||
**Tasarım Kararları:**
|
||||
- `urn:graph:retrieval`'a yazın (genel açıklanabilirlik grafiği)
|
||||
- Şu anda doğrusal bağımlılık zinciri (analiz N → wasDerivedFrom → analiz N-1)
|
||||
- Araçlar, kayıt alınmayan, opak kara kutulardır (sadece girdi/çıktı kaydedilir)
|
||||
- DAG desteği, gelecekteki bir yinelemeye ertelenmiştir
|
||||
|
||||
## Varlık Türleri
|
||||
|
||||
Hem GraphRAG hem de Agent, TrustGraph'e özgü alt türlere sahip olan PROV-O'yu temel ontoloji olarak kullanır:
|
||||
|
||||
### GraphRAG Türleri
|
||||
| Varlık | PROV-O Türü | TG Türleri | Açıklama |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Soru | `prov:Activity` | `tg:Question`, `tg:GraphRagQuestion` | Kullanıcının sorgusu |
|
||||
| Keşif | `prov:Entity` | `tg:Exploration` | Bilgi grafiğinden alınan kenarlar |
|
||||
| Odak | `prov:Entity` | `tg:Focus` | Akıl yürütmeyle seçilen kenarlar |
|
||||
| Sentez | `prov:Entity` | `tg:Synthesis` | Sonuç |
|
||||
|
||||
### Ajan Türleri
|
||||
| Varlık | PROV-O Türü | TG Türleri | Açıklama |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Soru | `prov:Activity` | `tg:Question`, `tg:AgentQuestion` | Kullanıcının sorgusu |
|
||||
| Analiz | `prov:Entity` | `tg:Analysis` | Her düşünme/eylem/gözlem döngüsü |
|
||||
| Sonuç | `prov:Entity` | `tg:Conclusion` | Sonuç |
|
||||
|
||||
### Belge RAG Türleri
|
||||
| Varlık | PROV-O Türü | TG Türleri | Açıklama |
|
||||
|--------|-------------|----------|-------------|
|
||||
| Soru | `prov:Activity` | `tg:Question`, `tg:DocRagQuestion` | Kullanıcının sorgusu |
|
||||
| Keşif | `prov:Entity` | `tg:Exploration` | Belge deposundan alınan parçalar |
|
||||
| Sentez | `prov:Entity` | `tg:Synthesis` | Sonuç |
|
||||
|
||||
**Not:** Belge RAG, GraphRAG'ın türlerinin bir alt kümesini kullanır (kenar seçimi/akıl yürütme aşaması olmadığından Odak adımı yoktur).
|
||||
|
||||
### Soru Alt Türleri
|
||||
|
||||
Tüm Soru varlıkları `tg:Question`'ı temel tür olarak paylaşır, ancak geri alma mekanizmasını tanımlamak için özel bir alt türe sahiptir:
|
||||
|
||||
| Alt Tür | URI Kalıbı | Mekanizma |
|
||||
|---------|-------------|-----------|
|
||||
| `tg:GraphRagQuestion` | `urn:trustgraph:question:{uuid}` | Bilgi grafiği RAG |
|
||||
| `tg:DocRagQuestion` | `urn:trustgraph:docrag:{uuid}` | Belge/parça RAG |
|
||||
| `tg:AgentQuestion` | `urn:trustgraph:agent:{uuid}` | ReAct ajanı |
|
||||
|
||||
Bu, tüm soruların `tg:Question` aracılığıyla sorgulanabilmesini sağlarken, alt tür aracılığıyla belirli bir mekanizma ile filtrelenmesini sağlar.
|
||||
|
||||
## Kaynak Modeli
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:agent:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis1 (urn:trustgraph:agent:{uuid}/i1)
|
||||
│
|
||||
│ tg:thought = "I need to query the knowledge base..."
|
||||
│ tg:action = "knowledge-query"
|
||||
│ tg:arguments = {"question": "..."}
|
||||
│ tg:observation = "Result from tool..."
|
||||
│ rdf:type = prov:Entity, tg:Analysis
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis2 (urn:trustgraph:agent:{uuid}/i2)
|
||||
│ ...
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Conclusion (urn:trustgraph:agent:{uuid}/final)
|
||||
│
|
||||
│ tg:answer = "The final response..."
|
||||
│ rdf:type = prov:Entity, tg:Conclusion
|
||||
```
|
||||
|
||||
### Belge RAG (Retrieval-Augmented Generation) Kaynak Modeli
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:docrag:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasGeneratedBy
|
||||
│
|
||||
Exploration (urn:trustgraph:docrag:{uuid}/exploration)
|
||||
│
|
||||
│ tg:chunkCount = 5
|
||||
│ tg:selectedChunk = "chunk-id-1"
|
||||
│ tg:selectedChunk = "chunk-id-2"
|
||||
│ ...
|
||||
│ rdf:type = prov:Entity, tg:Exploration
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Synthesis (urn:trustgraph:docrag:{uuid}/synthesis)
|
||||
│
|
||||
│ tg:content = "The synthesized answer..."
|
||||
│ rdf:type = prov:Entity, tg:Synthesis
|
||||
```
|
||||
|
||||
## Gerekli Değişiklikler
|
||||
|
||||
### 1. Şema Değişiklikleri
|
||||
|
||||
**Dosya:** `trustgraph-base/trustgraph/schema/services/agent.py`
|
||||
|
||||
`AgentRequest`'ye `session_id` ve `collection` alanlarını ekleyin:
|
||||
```python
|
||||
@dataclass
|
||||
class AgentRequest:
|
||||
question: str = ""
|
||||
state: str = ""
|
||||
group: list[str] | None = None
|
||||
history: list[AgentStep] = field(default_factory=list)
|
||||
user: str = ""
|
||||
collection: str = "default" # NEW: Collection for provenance traces
|
||||
streaming: bool = False
|
||||
session_id: str = "" # NEW: For provenance tracking across iterations
|
||||
```
|
||||
|
||||
**Dosya:** `trustgraph-base/trustgraph/messaging/translators/agent.py`
|
||||
|
||||
Çeviriciyi, `session_id` ve `collection`'i hem `to_pulsar()` hem de `from_pulsar()` içinde işleyebilecek şekilde güncelleyin.
|
||||
|
||||
### 2. Ajan Hizmetine Açıklanabilirlik Üreticisini Ekle
|
||||
|
||||
**Dosya:** `trustgraph-flow/trustgraph/agent/react/service.py`
|
||||
|
||||
Bir "açıklanabilirlik" üreticisi kaydedin (GraphRAG ile aynı yapı):
|
||||
```python
|
||||
from ... base import ProducerSpec
|
||||
from ... schema import Triples
|
||||
|
||||
# In __init__:
|
||||
self.register_specification(
|
||||
ProducerSpec(
|
||||
name = "explainability",
|
||||
schema = Triples,
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### 3. Kaynak Üçlü Oluşturma
|
||||
|
||||
**Dosya:** `trustgraph-base/trustgraph/provenance/agent.py`
|
||||
|
||||
Yardımcı fonksiyonlar oluşturun (GraphRAG'in `question_triples`, `exploration_triples`, vb. gibi):
|
||||
```python
|
||||
def agent_session_triples(session_uri, query, timestamp):
|
||||
"""Generate triples for agent Question."""
|
||||
return [
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=PROV_ACTIVITY),
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=TG_QUESTION),
|
||||
Triple(s=session_uri, p=TG_QUERY, o=query),
|
||||
Triple(s=session_uri, p=PROV_STARTED_AT_TIME, o=timestamp),
|
||||
]
|
||||
|
||||
def agent_iteration_triples(iteration_uri, parent_uri, thought, action, arguments, observation):
|
||||
"""Generate triples for one Analysis step."""
|
||||
return [
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=TG_ANALYSIS),
|
||||
Triple(s=iteration_uri, p=TG_THOUGHT, o=thought),
|
||||
Triple(s=iteration_uri, p=TG_ACTION, o=action),
|
||||
Triple(s=iteration_uri, p=TG_ARGUMENTS, o=json.dumps(arguments)),
|
||||
Triple(s=iteration_uri, p=TG_OBSERVATION, o=observation),
|
||||
Triple(s=iteration_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
|
||||
def agent_final_triples(final_uri, parent_uri, answer):
|
||||
"""Generate triples for Conclusion."""
|
||||
return [
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=TG_CONCLUSION),
|
||||
Triple(s=final_uri, p=TG_ANSWER, o=answer),
|
||||
Triple(s=final_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
```
|
||||
|
||||
### 4. Tür Tanımları
|
||||
|
||||
**Dosya:** `trustgraph-base/trustgraph/provenance/namespaces.py`
|
||||
|
||||
Açıklanabilirlik varlık türlerini ve ajan özniteliklerini ekleyin:
|
||||
```python
|
||||
# Explainability entity types (used by both GraphRAG and Agent)
|
||||
TG_QUESTION = TG + "Question"
|
||||
TG_EXPLORATION = TG + "Exploration"
|
||||
TG_FOCUS = TG + "Focus"
|
||||
TG_SYNTHESIS = TG + "Synthesis"
|
||||
TG_ANALYSIS = TG + "Analysis"
|
||||
TG_CONCLUSION = TG + "Conclusion"
|
||||
|
||||
# Agent predicates
|
||||
TG_THOUGHT = TG + "thought"
|
||||
TG_ACTION = TG + "action"
|
||||
TG_ARGUMENTS = TG + "arguments"
|
||||
TG_OBSERVATION = TG + "observation"
|
||||
TG_ANSWER = TG + "answer"
|
||||
```
|
||||
|
||||
## Değiştirilen Dosyalar
|
||||
|
||||
| Dosya | Değişiklik |
|
||||
|------|--------|
|
||||
| `trustgraph-base/trustgraph/schema/services/agent.py` | AgentRequest'e session_id ve collection eklendi |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/agent.py` | Yeni alanlar için çevirici güncellendi |
|
||||
| `trustgraph-base/trustgraph/provenance/namespaces.py` | Varlık türleri, ajan önişlemleri ve Document RAG önişlemleri eklendi |
|
||||
| `trustgraph-base/trustgraph/provenance/triples.py` | GraphRAG üçlü oluşturucularına TG türleri eklendi, Document RAG üçlü oluşturucuları eklendi |
|
||||
| `trustgraph-base/trustgraph/provenance/uris.py` | Document RAG URI oluşturucuları eklendi |
|
||||
| `trustgraph-base/trustgraph/provenance/__init__.py` | Yeni türler, önişlemler ve Document RAG fonksiyonları dışa aktarıldı |
|
||||
| `trustgraph-base/trustgraph/schema/services/retrieval.py` | DocumentRagResponse'a explain_id ve explain_graph eklendi |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/retrieval.py` | Açıklanabilirlik alanları için DocumentRagResponseTranslator güncellendi |
|
||||
| `trustgraph-flow/trustgraph/agent/react/service.py` | Açıklanabilirlik üretici + kayıt mantığı eklendi |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` | Açıklanabilirlik geri çağırması eklendi ve kaynak üçlüleri yayıldı |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` | Açıklanabilirlik üretici eklendi ve geri çağırma ile bağlandı |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | Ajan izleme türleri işlendi |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | Ajan oturumları, GraphRAG ile birlikte listelendi |
|
||||
|
||||
## Oluşturulan Dosyalar
|
||||
|
||||
| Dosya | Amaç |
|
||||
|------|---------|
|
||||
| `trustgraph-base/trustgraph/provenance/agent.py` | Ajan özel üçlü oluşturucuları |
|
||||
|
||||
## CLI Güncellemeleri
|
||||
|
||||
**Algılama:** Hem GraphRAG hem de Ajan Soruları `tg:Question` türündedir. Aşağıdakilerle ayırt edilir:
|
||||
1. URI kalıbı: `urn:trustgraph:agent:` vs `urn:trustgraph:question:`
|
||||
2. Türetilen varlıklar: `tg:Analysis` (ajan) vs `tg:Exploration` (GraphRAG)
|
||||
|
||||
**`list_explain_traces.py`:**
|
||||
- Tür sütununu (Ajan vs GraphRAG) gösterir
|
||||
|
||||
**`show_explain_trace.py`:**
|
||||
- İzleme türünü otomatik olarak algılar
|
||||
- Ajan işleme, şu öğeleri gösterir: Soru → Analiz adımı(ları) → Sonuç
|
||||
|
||||
## Geriye Dönük Uyumluluk
|
||||
|
||||
- `session_id` varsayılan olarak `""`'dir - eski istekler çalışır, ancak kaynak bilgisi olmayacaktır
|
||||
- `collection` varsayılan olarak `"default"`'dir - makul bir yedekleme
|
||||
- CLI, her iki izleme türünü de sorunsuz bir şekilde işler
|
||||
|
||||
## Doğrulama
|
||||
|
||||
```bash
|
||||
# Run an agent query
|
||||
tg-invoke-agent -q "What is the capital of France?"
|
||||
|
||||
# List traces (should show agent sessions with Type column)
|
||||
tg-list-explain-traces -U trustgraph -C default
|
||||
|
||||
# Show agent trace
|
||||
tg-show-explain-trace "urn:trustgraph:agent:xxx"
|
||||
```
|
||||
|
||||
## Gelecek Çalışmalar (Bu PR'de Değil)
|
||||
|
||||
- DAG bağımlılıkları (analiz N, birden fazla önceki analizden sonuçları kullandığında)
|
||||
- Araçlara özel köken bağlantısı (KnowledgeQuery → GraphRAG izi)
|
||||
- Akışlı köken yayını (sonunda toplu olarak değil, işlem sırasında yayınla)
|
||||
280
docs/tech-specs/agent-explainability.zh-cn.md
Normal file
280
docs/tech-specs/agent-explainability.zh-cn.md
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Agent Explainability: Provenance Recording"
|
||||
parent: "Chinese (Beta)"
|
||||
---
|
||||
|
||||
# Agent Explainability: Provenance Recording
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## 概述
|
||||
|
||||
为使代理会话可追溯和可调试,并将代理循环中的溯源记录添加到 React 代理中,从而使用与 GraphRAG 相同的可解释性基础设施。
|
||||
|
||||
**设计决策:**
|
||||
写入 `urn:graph:retrieval` (通用可解释性图)
|
||||
目前采用线性依赖链 (分析 N → wasDerivedFrom → 分析 N-1)
|
||||
工具是不可见的黑盒 (仅记录输入/输出)
|
||||
DAG 支持计划在未来迭代中实现
|
||||
|
||||
## 实体类型
|
||||
|
||||
GraphRAG 和 Agent 都使用 PROV-O 作为基础本体,并具有 TrustGraph 特定的子类型:
|
||||
|
||||
### GraphRAG 类型
|
||||
| 实体 | PROV-O 类型 | TG 类型 | 描述 |
|
||||
|--------|-------------|----------|-------------|
|
||||
| 问题 | `prov:Activity` | `tg:Question`, `tg:GraphRagQuestion` | 用户的查询 |
|
||||
| 探索 | `prov:Entity` | `tg:Exploration` | 从知识图谱检索的边 |
|
||||
| 重点 | `prov:Entity` | `tg:Focus` | 带有推理的选定边 |
|
||||
| 合成 | `prov:Entity` | `tg:Synthesis` | 最终答案 |
|
||||
|
||||
### Agent 类型
|
||||
| 实体 | PROV-O 类型 | TG 类型 | 描述 |
|
||||
|--------|-------------|----------|-------------|
|
||||
| 问题 | `prov:Activity` | `tg:Question`, `tg:AgentQuestion` | 用户的查询 |
|
||||
| 分析 | `prov:Entity` | `tg:Analysis` | 每个思考/行动/观察周期 |
|
||||
| 结论 | `prov:Entity` | `tg:Conclusion` | 最终答案 |
|
||||
|
||||
### Document RAG 类型
|
||||
| 实体 | PROV-O 类型 | TG 类型 | 描述 |
|
||||
|--------|-------------|----------|-------------|
|
||||
| 问题 | `prov:Activity` | `tg:Question`, `tg:DocRagQuestion` | 用户的查询 |
|
||||
| 探索 | `prov:Entity` | `tg:Exploration` | 从文档存储中检索的块 |
|
||||
| 合成 | `prov:Entity` | `tg:Synthesis` | 最终答案 |
|
||||
|
||||
**注意:** Document RAG 使用 GraphRAG 类型的子集 (没有“重点”步骤,因为没有边选择/推理阶段)。
|
||||
|
||||
### 问题子类型
|
||||
|
||||
所有“问题”实体都共享 `tg:Question` 作为基本类型,但具有特定的子类型以标识检索机制:
|
||||
|
||||
| 子类型 | URI 模式 | 机制 |
|
||||
|---------|-------------|-----------|
|
||||
| `tg:GraphRagQuestion` | `urn:trustgraph:question:{uuid}` | 知识图谱 RAG |
|
||||
| `tg:DocRagQuestion` | `urn:trustgraph:docrag:{uuid}` | 文档/块 RAG |
|
||||
| `tg:AgentQuestion` | `urn:trustgraph:agent:{uuid}` | ReAct 代理 |
|
||||
|
||||
这允许通过 `tg:Question` 查询所有问题,同时通过子类型过滤特定机制。
|
||||
|
||||
## 溯源模型
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:agent:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis1 (urn:trustgraph:agent:{uuid}/i1)
|
||||
│
|
||||
│ tg:thought = "I need to query the knowledge base..."
|
||||
│ tg:action = "knowledge-query"
|
||||
│ tg:arguments = {"question": "..."}
|
||||
│ tg:observation = "Result from tool..."
|
||||
│ rdf:type = prov:Entity, tg:Analysis
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Analysis2 (urn:trustgraph:agent:{uuid}/i2)
|
||||
│ ...
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Conclusion (urn:trustgraph:agent:{uuid}/final)
|
||||
│
|
||||
│ tg:answer = "The final response..."
|
||||
│ rdf:type = prov:Entity, tg:Conclusion
|
||||
```
|
||||
|
||||
### 文档检索增强生成(RAG)溯源模型
|
||||
|
||||
```
|
||||
Question (urn:trustgraph:docrag:{uuid})
|
||||
│
|
||||
│ tg:query = "User's question"
|
||||
│ prov:startedAtTime = timestamp
|
||||
│ rdf:type = prov:Activity, tg:Question
|
||||
│
|
||||
↓ prov:wasGeneratedBy
|
||||
│
|
||||
Exploration (urn:trustgraph:docrag:{uuid}/exploration)
|
||||
│
|
||||
│ tg:chunkCount = 5
|
||||
│ tg:selectedChunk = "chunk-id-1"
|
||||
│ tg:selectedChunk = "chunk-id-2"
|
||||
│ ...
|
||||
│ rdf:type = prov:Entity, tg:Exploration
|
||||
│
|
||||
↓ prov:wasDerivedFrom
|
||||
│
|
||||
Synthesis (urn:trustgraph:docrag:{uuid}/synthesis)
|
||||
│
|
||||
│ tg:content = "The synthesized answer..."
|
||||
│ rdf:type = prov:Entity, tg:Synthesis
|
||||
```
|
||||
|
||||
## 需要修改的内容
|
||||
|
||||
### 1. 模式更改
|
||||
|
||||
**文件:** `trustgraph-base/trustgraph/schema/services/agent.py`
|
||||
|
||||
向 `AgentRequest` 添加 `session_id` 和 `collection` 字段:
|
||||
```python
|
||||
@dataclass
|
||||
class AgentRequest:
|
||||
question: str = ""
|
||||
state: str = ""
|
||||
group: list[str] | None = None
|
||||
history: list[AgentStep] = field(default_factory=list)
|
||||
user: str = ""
|
||||
collection: str = "default" # NEW: Collection for provenance traces
|
||||
streaming: bool = False
|
||||
session_id: str = "" # NEW: For provenance tracking across iterations
|
||||
```
|
||||
|
||||
**文件:** `trustgraph-base/trustgraph/messaging/translators/agent.py`
|
||||
|
||||
更新翻译器,使其能够处理 `session_id` 和 `collection`,并在 `to_pulsar()` 和 `from_pulsar()` 中均能正确处理。
|
||||
|
||||
### 2. 向 Agent Service 添加可解释性生产者
|
||||
|
||||
**文件:** `trustgraph-flow/trustgraph/agent/react/service.py`
|
||||
|
||||
注册一个“可解释性”生产者(与 GraphRAG 相同模式):
|
||||
```python
|
||||
from ... base import ProducerSpec
|
||||
from ... schema import Triples
|
||||
|
||||
# In __init__:
|
||||
self.register_specification(
|
||||
ProducerSpec(
|
||||
name = "explainability",
|
||||
schema = Triples,
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### 3. 溯源三元组生成
|
||||
|
||||
**文件:** `trustgraph-base/trustgraph/provenance/agent.py`
|
||||
|
||||
创建辅助函数(类似于 GraphRAG 的 `question_triples`、`exploration_triples` 等):
|
||||
```python
|
||||
def agent_session_triples(session_uri, query, timestamp):
|
||||
"""Generate triples for agent Question."""
|
||||
return [
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=PROV_ACTIVITY),
|
||||
Triple(s=session_uri, p=RDF_TYPE, o=TG_QUESTION),
|
||||
Triple(s=session_uri, p=TG_QUERY, o=query),
|
||||
Triple(s=session_uri, p=PROV_STARTED_AT_TIME, o=timestamp),
|
||||
]
|
||||
|
||||
def agent_iteration_triples(iteration_uri, parent_uri, thought, action, arguments, observation):
|
||||
"""Generate triples for one Analysis step."""
|
||||
return [
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=iteration_uri, p=RDF_TYPE, o=TG_ANALYSIS),
|
||||
Triple(s=iteration_uri, p=TG_THOUGHT, o=thought),
|
||||
Triple(s=iteration_uri, p=TG_ACTION, o=action),
|
||||
Triple(s=iteration_uri, p=TG_ARGUMENTS, o=json.dumps(arguments)),
|
||||
Triple(s=iteration_uri, p=TG_OBSERVATION, o=observation),
|
||||
Triple(s=iteration_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
|
||||
def agent_final_triples(final_uri, parent_uri, answer):
|
||||
"""Generate triples for Conclusion."""
|
||||
return [
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=PROV_ENTITY),
|
||||
Triple(s=final_uri, p=RDF_TYPE, o=TG_CONCLUSION),
|
||||
Triple(s=final_uri, p=TG_ANSWER, o=answer),
|
||||
Triple(s=final_uri, p=PROV_WAS_DERIVED_FROM, o=parent_uri),
|
||||
]
|
||||
```
|
||||
|
||||
### 4. 类型定义
|
||||
|
||||
**文件:** `trustgraph-base/trustgraph/provenance/namespaces.py`
|
||||
|
||||
添加可解释性实体类型和代理谓词:
|
||||
```python
|
||||
# Explainability entity types (used by both GraphRAG and Agent)
|
||||
TG_QUESTION = TG + "Question"
|
||||
TG_EXPLORATION = TG + "Exploration"
|
||||
TG_FOCUS = TG + "Focus"
|
||||
TG_SYNTHESIS = TG + "Synthesis"
|
||||
TG_ANALYSIS = TG + "Analysis"
|
||||
TG_CONCLUSION = TG + "Conclusion"
|
||||
|
||||
# Agent predicates
|
||||
TG_THOUGHT = TG + "thought"
|
||||
TG_ACTION = TG + "action"
|
||||
TG_ARGUMENTS = TG + "arguments"
|
||||
TG_OBSERVATION = TG + "observation"
|
||||
TG_ANSWER = TG + "answer"
|
||||
```
|
||||
|
||||
## 文件修改
|
||||
|
||||
| 文件 | 更改 |
|
||||
|------|--------|
|
||||
| `trustgraph-base/trustgraph/schema/services/agent.py` | 向 AgentRequest 添加 session_id 和 collection |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/agent.py` | 更新翻译器以适应新字段 |
|
||||
| `trustgraph-base/trustgraph/provenance/namespaces.py` | 添加实体类型、agent谓词和 Document RAG 谓词 |
|
||||
| `trustgraph-base/trustgraph/provenance/triples.py` | 向 GraphRAG 三元组构建器添加 TG 类型,添加 Document RAG 三元组构建器 |
|
||||
| `trustgraph-base/trustgraph/provenance/uris.py` | 添加 Document RAG URI 生成器 |
|
||||
| `trustgraph-base/trustgraph/provenance/__init__.py` | 导出新类型、谓词和 Document RAG 函数 |
|
||||
| `trustgraph-base/trustgraph/schema/services/retrieval.py` | 向 DocumentRagResponse 添加 explain_id 和 explain_graph |
|
||||
| `trustgraph-base/trustgraph/messaging/translators/retrieval.py` | 更新 DocumentRagResponseTranslator 以适应可解释性字段 |
|
||||
| `trustgraph-flow/trustgraph/agent/react/service.py` | 添加可解释性生产者 + 记录逻辑 |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` | 添加可解释性回调并发出溯源三元组 |
|
||||
| `trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` | 添加可解释性生产者并连接回调 |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | 处理 agent 跟踪类型 |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | 在 GraphRAG 旁边列出 agent 会话 |
|
||||
|
||||
## 创建的文件
|
||||
|
||||
| 文件 | 目的 |
|
||||
|------|---------|
|
||||
| `trustgraph-base/trustgraph/provenance/agent.py` | Agent 相关的三元组生成器 |
|
||||
|
||||
## CLI 更新
|
||||
|
||||
**检测:** 无论是 GraphRAG 还是 Agent 问题,都具有 `tg:Question` 类型。通过以下方式区分:
|
||||
1. URI 模式:`urn:trustgraph:agent:` vs `urn:trustgraph:question:`
|
||||
2. 派生实体:`tg:Analysis` (agent) vs `tg:Exploration` (GraphRAG)
|
||||
|
||||
**`list_explain_traces.py`:**
|
||||
显示类型列(Agent vs GraphRAG)
|
||||
|
||||
**`show_explain_trace.py`:**
|
||||
自动检测跟踪类型
|
||||
Agent 渲染显示:问题 → 分析步骤(s) → 结论
|
||||
|
||||
## 向后兼容性
|
||||
|
||||
`session_id` 默认为 `""` - 旧请求有效,但将不具有溯源信息
|
||||
`collection` 默认为 `"default"` - 合理的备选方案
|
||||
CLI 能够优雅地处理两种跟踪类型
|
||||
|
||||
## 验证
|
||||
|
||||
```bash
|
||||
# Run an agent query
|
||||
tg-invoke-agent -q "What is the capital of France?"
|
||||
|
||||
# List traces (should show agent sessions with Type column)
|
||||
tg-list-explain-traces -U trustgraph -C default
|
||||
|
||||
# Show agent trace
|
||||
tg-show-explain-trace "urn:trustgraph:agent:xxx"
|
||||
```
|
||||
|
||||
## 未来工作(不在本次 PR 中)
|
||||
|
||||
DAG 依赖关系(当分析 N 使用来自多个先前分析的结果时)
|
||||
特定于工具的溯源链接(KnowledgeQuery → 它的 GraphRAG 跟踪)
|
||||
流式溯源输出(在过程中输出,而不是在最后批量输出)
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "TrustGraph Agent Orchestration — Technical Specification"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# TrustGraph Agent Orchestration — Technical Specification
|
||||
|
||||
## Overview
|
||||
|
|
|
|||
113
docs/tech-specs/architecture-principles.ar.md
Normal file
113
docs/tech-specs/architecture-principles.ar.md
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
layout: default
|
||||
title: "أسس هيكل الرسم البياني للمعرفة"
|
||||
parent: "Arabic (Beta)"
|
||||
---
|
||||
|
||||
# أسس هيكل الرسم البياني للمعرفة
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## الأساس الأول: نموذج الرسم البياني للعلاقة بين الموضوع والمسند والموضوع (SPO)
|
||||
**القرار**: اعتماد نموذج SPO/RDF كنموذج تمثيل المعرفة الأساسي
|
||||
|
||||
**السبب**:
|
||||
يوفر أقصى قدر من المرونة وقابلية التشغيل البيني مع تقنيات الرسم البياني الحالية
|
||||
يمكّن الترجمة السلسة إلى لغات استعلام عن الرسم البياني الأخرى (مثل SPO → Cypher، ولكن ليس العكس)
|
||||
يخلق أساسًا "يفتح الكثير" من القدرات اللاحقة
|
||||
يدعم كل من علاقات العقدة إلى العقدة (SPO) وعلاقات العقدة إلى القيمة الحرفية (RDF)
|
||||
|
||||
**التنفيذ**:
|
||||
الهيكل الأساسي للبيانات: `node → edge → {node | literal}`
|
||||
الحفاظ على التوافق مع معايير RDF مع دعم عمليات SPO الموسعة
|
||||
|
||||
## الأساس الثاني: تكامل الرسم البياني الأصلي لنماذج اللغة الكبيرة (LLM)
|
||||
**القرار**: تحسين هيكل وعمليات الرسم البياني للتفاعل مع نماذج اللغة الكبيرة
|
||||
|
||||
**السبب**:
|
||||
الحالة الرئيسية هي تفاعل نماذج اللغة الكبيرة مع الرسوم البيانية للمعرفة
|
||||
يجب أن تعطي خيارات تقنية الرسم البياني الأولوية لتوافق نماذج اللغة الكبيرة على اعتبارات أخرى
|
||||
يمكّن سير عمل معالجة اللغة الطبيعية التي تستفيد من المعرفة المنظمة
|
||||
|
||||
**التنفيذ**:
|
||||
تصميم مخططات الرسم البياني التي يمكن لنماذج اللغة الكبيرة الاستدلال عليها بشكل فعال
|
||||
التحسين لأنماط التفاعل الشائعة لنماذج اللغة الكبيرة
|
||||
|
||||
## الأساس الثالث: التنقل في الرسم البياني القائم على التضمين
|
||||
**القرار**: تنفيذ تعيين مباشر من استعلامات اللغة الطبيعية إلى عقد الرسم البياني عبر التضمينات
|
||||
|
||||
**السبب**:
|
||||
يمكّن المسار الأبسط من استعلام معالجة اللغة الطبيعية إلى التنقل في الرسم البياني
|
||||
يتجنب خطوات توليد استعلام وسيطة معقدة
|
||||
يوفر قدرات بحث دلالي فعالة داخل هيكل الرسم البياني
|
||||
|
||||
**التنفيذ**:
|
||||
`NLP Query → Graph Embeddings → Graph Nodes`
|
||||
الحفاظ على تمثيلات التضمين لجميع كيانات الرسم البياني
|
||||
دعم مطابقة تشابه دلالي مباشر لحل الاستعلامات
|
||||
|
||||
## الأساس الرابع: حل الكيانات الموزع مع المعرفات الحتمية
|
||||
**القرار**: دعم استخراج المعرفة المتوازي مع تحديد الكيانات الحتمي (قاعدة 80٪)
|
||||
|
||||
**السبب**:
|
||||
**مثالي**: يتيح استخراج العملية الفردية مع رؤية حالة كاملة حل الكيانات المثالي
|
||||
**الواقع**: تتطلب متطلبات قابلية التوسع قدرات معالجة متوازية
|
||||
**حل وسط**: التصميم من أجل تحديد الكيانات الحتمي عبر العمليات الموزعة
|
||||
|
||||
**التنفيذ**:
|
||||
تطوير آليات لتوليد معرفات متسقة وفريدة عبر أدوات استخراج المعرفة المختلفة
|
||||
يجب أن يتم حل نفس الكيان المذكور في عمليات مختلفة إلى نفس المعرف
|
||||
الاعتراف بأنه قد تتطلب ~20٪ من الحالات الخاصة نماذج معالجة بديلة
|
||||
تصميم آليات احتياطية لسيناريوهات حل الكيانات المعقدة
|
||||
|
||||
## الأساس الخامس: بنية قائمة على الأحداث مع النشر والاشتراك
|
||||
**القرار**: تنفيذ نظام رسائل النشر والاشتراك لتنسيق النظام
|
||||
|
||||
**السبب**:
|
||||
يمكّن الفصل بين مكونات استخراج وتخزين واستعلام المعرفة
|
||||
يدعم التحديثات والإشعارات في الوقت الفعلي عبر النظام
|
||||
يسهل سير عمل معالجة موزعة وقابلة للتطوير
|
||||
|
||||
**التنفيذ**:
|
||||
تنسيق مدفوع بالرسائل بين مكونات النظام
|
||||
تدفقات الأحداث لتحديثات المعرفة وإكمال الاستخراج ونتائج الاستعلام
|
||||
|
||||
## الأساس السادس: تواصل الوكيل القابل لإعادة الدخول
|
||||
**القرار**: دعم عمليات النشر والاشتراك القابلة لإعادة الدخول لمعالجة قائمة على الوكلاء
|
||||
|
||||
**السبب**:
|
||||
يمكّن سير عمل الوكيل المعقد حيث يمكن للوكلاء تشغيل والرد على بعضهم البعض
|
||||
يدعم خطوط أنابيب معالجة المعرفة المعقدة والمتعددة الخطوات
|
||||
يسمح بأنماط المعالجة التكرارية والتكرارية
|
||||
|
||||
**التنفيذ**:
|
||||
يجب أن يتعامل نظام النشر والاشتراك مع المكالمات القابلة لإعادة الدخول بأمان
|
||||
آليات تنسيق الوكيل التي تمنع الحلقات اللانهائية
|
||||
دعم تنسيق سير عمل الوكيل
|
||||
|
||||
## الأساس السابع: تكامل متجر البيانات العمودي
|
||||
**القرار**: ضمان توافق الاستعلام مع أنظمة التخزين العمودية
|
||||
|
||||
**السبب**:
|
||||
يمكّن الاستعلامات التحليلية الفعالة على مجموعات بيانات المعرفة الكبيرة
|
||||
يدعم حالات استخدام ذكاء الأعمال وإعداد التقارير
|
||||
يربط بين تمثيل المعرفة القائم على الرسم البياني وسير العمل التحليلي التقليدي
|
||||
|
||||
**التنفيذ**:
|
||||
طبقة ترجمة الاستعلام: استعلامات الرسم البياني → استعلامات عمودية
|
||||
استراتيجية تخزين هجينة تدعم عمليات الرسم البياني وأحمال العمل التحليلية
|
||||
الحفاظ على أداء الاستعلام عبر كلا النماذجين
|
||||
|
||||
--
|
||||
|
||||
## ملخص مبادئ البنية
|
||||
|
||||
1. **المرونة أولاً**: يوفر نموذج SPO أقصى قدر من القدرة على التكيف
|
||||
2. **التحسين لنماذج اللغة الكبيرة**: تأخذ جميع القرارات التصميمية في الاعتبار متطلبات تفاعل نماذج اللغة الكبيرة
|
||||
3. **الكفاءة الدلالية**: تعيين مباشر من التضمين إلى العقدة لأداء استعلام أمثل
|
||||
4. **قابلية التوسع العملية**: الموازنة بين الدقة المثالية والمعالجة الموزعة العملية
|
||||
5. **التنسيق القائم على الأحداث**: يمكّن النشر والاشتراك من الفصل وقابلية التوسع
|
||||
6. **صديقة للوكيل**: دعم سير عمل معالجة متعددة الوكلاء
|
||||
7. **التوافق التحليلي**: ربط بين نماذج الرسم البياني والأعمدة للاستعلامات الشاملة
|
||||
|
||||
تحدد هذه الأسس بنية رسم بياني للمعرفة تحقق التوازن بين الدقة النظرية ومتطلبات قابلية التوسع العملية، ومحسنة للتكامل مع نماذج اللغة الكبيرة والمعالجة الموزعة.
|
||||
113
docs/tech-specs/architecture-principles.es.md
Normal file
113
docs/tech-specs/architecture-principles.es.md
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Fundamentos de la Arquitectura del Gráfico de Conocimiento"
|
||||
parent: "Spanish (Beta)"
|
||||
---
|
||||
|
||||
# Fundamentos de la Arquitectura del Gráfico de Conocimiento
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Fundamento 1: Modelo de Gráfico Sujeto-Predicado-Objeto (SPO)
|
||||
**Decisión**: Adoptar SPO/RDF como el modelo de representación de conocimiento central.
|
||||
|
||||
**Justificación**:
|
||||
Proporciona la máxima flexibilidad e interoperabilidad con las tecnologías de gráficos existentes.
|
||||
Permite la traducción fluida a otros lenguajes de consulta de gráficos (por ejemplo, SPO → Cypher, pero no al revés).
|
||||
Crea una base que "desbloquea muchas" capacidades posteriores.
|
||||
Admite tanto relaciones de nodo a nodo (SPO) como relaciones de nodo a literal (RDF).
|
||||
|
||||
**Implementación**:
|
||||
Estructura de datos central: `node → edge → {node | literal}`
|
||||
Mantener la compatibilidad con los estándares RDF al tiempo que se admiten operaciones SPO extendidas.
|
||||
|
||||
## Fundamento 2: Integración Nativa del Gráfico de Conocimiento con LLM
|
||||
**Decisión**: Optimizar la estructura y las operaciones del gráfico de conocimiento para la interacción con LLM.
|
||||
|
||||
**Justificación**:
|
||||
El caso de uso principal implica que los LLM interactúen con los gráficos de conocimiento.
|
||||
Las opciones de tecnología de gráficos deben priorizar la compatibilidad con LLM por encima de otras consideraciones.
|
||||
Permite flujos de trabajo de procesamiento del lenguaje natural que aprovechan el conocimiento estructurado.
|
||||
|
||||
**Implementación**:
|
||||
Diseñar esquemas de gráficos que los LLM puedan comprender y razonar eficazmente.
|
||||
Optimizar para patrones de interacción comunes con LLM.
|
||||
|
||||
## Fundamento 3: Navegación del Gráfico Basada en Incrustaciones
|
||||
**Decisión**: Implementar un mapeo directo de las consultas de lenguaje natural a los nodos del gráfico a través de incrustaciones.
|
||||
|
||||
**Justificación**:
|
||||
Permite la ruta más sencilla posible desde la consulta de PNL hasta la navegación del gráfico.
|
||||
Evita pasos complejos de generación de consultas intermedias.
|
||||
Proporciona capacidades de búsqueda semántica eficientes dentro de la estructura del gráfico.
|
||||
|
||||
**Implementación**:
|
||||
`NLP Query → Graph Embeddings → Graph Nodes`
|
||||
Mantener representaciones de incrustación para todas las entidades del gráfico.
|
||||
Admitir la coincidencia de similitud semántica directa para la resolución de consultas.
|
||||
|
||||
## Fundamento 4: Resolución de Entidades Distribuidas con Identificadores Deterministas
|
||||
**Decisión**: Admitir la extracción de conocimiento en paralelo con la identificación determinista de entidades (regla del 80%).
|
||||
|
||||
**Justificación**:
|
||||
**Ideal**: La extracción en un solo proceso con visibilidad completa del estado permite una resolución de entidades perfecta.
|
||||
**Realidad**: Los requisitos de escalabilidad exigen capacidades de procesamiento en paralelo.
|
||||
**Compromiso**: Diseñar para la identificación determinista de entidades en procesos distribuidos.
|
||||
|
||||
**Implementación**:
|
||||
Desarrollar mecanismos para generar identificadores consistentes y únicos en diferentes extractores de conocimiento.
|
||||
La misma entidad mencionada en diferentes procesos debe resolverse en el mismo identificador.
|
||||
Reconocer que aproximadamente el 20% de los casos extremos pueden requerir modelos de procesamiento alternativos.
|
||||
Diseñar mecanismos de respaldo para escenarios complejos de resolución de entidades.
|
||||
|
||||
## Fundamento 5: Arquitectura Orientada a Eventos con Publicación-Suscripción
|
||||
**Decisión**: Implementar un sistema de mensajería de publicación-suscripción para la coordinación del sistema.
|
||||
|
||||
**Justificación**:
|
||||
Permite un acoplamiento débil entre los componentes de extracción, almacenamiento y consulta de conocimiento.
|
||||
Admite actualizaciones y notificaciones en tiempo real en todo el sistema.
|
||||
Facilita flujos de trabajo de procesamiento distribuidos y escalables.
|
||||
|
||||
**Implementación**:
|
||||
Coordinación basada en mensajes entre los componentes del sistema.
|
||||
Flujos de eventos para actualizaciones de conocimiento, finalización de la extracción y resultados de consultas.
|
||||
|
||||
## Fundamento 6: Comunicación de Agentes Reentrantes
|
||||
**Decisión**: Admitir operaciones de publicación-suscripción reentrantes para el procesamiento basado en agentes.
|
||||
|
||||
**Justificación**:
|
||||
Permite flujos de trabajo sofisticados de agentes donde los agentes pueden activar y responder entre sí.
|
||||
Admite canalizaciones complejas de procesamiento de conocimiento con varios pasos.
|
||||
Permite patrones de procesamiento recursivos e iterativos.
|
||||
|
||||
**Implementación**:
|
||||
El sistema de publicación-suscripción debe manejar las llamadas reentrantes de forma segura.
|
||||
Mecanismos de coordinación de agentes que previenen bucles infinitos.
|
||||
Soporte para la orquestación de flujos de trabajo de agentes.
|
||||
|
||||
## Fundamento 7: Integración con Almacenes de Datos Columnares
|
||||
**Decisión**: Asegurar la compatibilidad de las consultas con los sistemas de almacenamiento columnar.
|
||||
|
||||
**Justificación**:
|
||||
Permite consultas analíticas eficientes sobre grandes conjuntos de datos de conocimiento.
|
||||
Admite casos de uso de inteligencia empresarial e informes.
|
||||
Une la representación de conocimiento basada en gráficos con los flujos de trabajo analíticos tradicionales.
|
||||
|
||||
**Implementación**:
|
||||
Capa de traducción de consultas: Consultas de gráfico → Consultas de columna.
|
||||
Estrategia de almacenamiento híbrida que admite tanto operaciones de gráfico como cargas de trabajo analíticas.
|
||||
Mantener el rendimiento de las consultas en ambos paradigmas.
|
||||
|
||||
--
|
||||
|
||||
## Resumen de los Principios de la Arquitectura
|
||||
|
||||
1. **Flexibilidad Primero**: El modelo SPO/RDF proporciona la máxima adaptabilidad.
|
||||
2. **Optimización para LLM**: Todas las decisiones de diseño consideran los requisitos de interacción con LLM.
|
||||
3. **Eficiencia Semántica**: Mapeo directo de incrustaciones a nodos para un rendimiento de consulta óptimo.
|
||||
4. **Escalabilidad Pragmática**: Equilibrar la precisión perfecta con el procesamiento distribuido práctico.
|
||||
5. **Coordinación Orientada a Eventos**: La publicación-suscripción permite un acoplamiento débil y la escalabilidad.
|
||||
6. **Amigable para Agentes**: Admite flujos de trabajo complejos de procesamiento basados en agentes.
|
||||
7. **Compatibilidad Analítica**: Une los paradigmas de gráficos y columnas para consultas integrales.
|
||||
|
||||
Estos fundamentos establecen una arquitectura de gráfico de conocimiento que equilibra la rigurosidad teórica con los requisitos prácticos de escalabilidad, optimizada para la integración con LLM y el procesamiento distribuido.
|
||||
113
docs/tech-specs/architecture-principles.he.md
Normal file
113
docs/tech-specs/architecture-principles.he.md
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
layout: default
|
||||
title: "יסודות ארכיטקטורת גרף ידע"
|
||||
parent: "Hebrew (Beta)"
|
||||
---
|
||||
|
||||
# יסודות ארכיטקטורת גרף ידע
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## יסוד 1: מודל גרף נושא-תכונה-אובייקט (SPO)
|
||||
**החלטה**: לאמץ את מודל SPO/RDF כמודל הייצוג הבסיסי של ידע.
|
||||
|
||||
**הצדקה**:
|
||||
מספק גמישות מרבית ותאימות עם טכנולוגיות גרף קיימות.
|
||||
מאפשר המרה חלקה לשפות שאילתות גרף אחרות (לדוגמה, SPO → Cypher, אך לא להיפך).
|
||||
יוצר בסיס ש"פותח הרבה" יכולות נלוות.
|
||||
תומך הן בקשרים בין צמתים (SPO) והן בקשרים בין צמתים לערכים (RDF).
|
||||
|
||||
**יישום**:
|
||||
מבנה נתונים מרכזי: `node → edge → {node | literal}`
|
||||
שמירה על תאימות לתקני RDF תוך תמיכה בפעולות SPO מורחבות.
|
||||
|
||||
## יסוד 2: שילוב גרף ידע מותאם למודלי שפה גדולים (LLM)
|
||||
**החלטה**: אופטימיזציה של מבנה ותפעול גרף ידע לאינטראקציה עם LLM.
|
||||
|
||||
**הצדקה**:
|
||||
מקרה שימוש עיקרי כולל LLM באינטראקציה עם גרפי ידע.
|
||||
בחירות טכנולוגיות גרף חייבות לתעדף תאימות ל-LLM על פני שיקולים אחרים.
|
||||
מאפשר זרימות עבודה של עיבוד שפה טבעית המנצלות ידע מובנה.
|
||||
|
||||
**יישום**:
|
||||
תכנון סכימות גרף ש-LLM יכולים להסיק מהן בצורה יעילה.
|
||||
אופטימיזציה לדפוסי אינטראקציה נפוצים של LLM.
|
||||
|
||||
## יסוד 3: ניווט גרף מבוסס הטבעות (Embeddings)
|
||||
**החלטה**: יישום מיפוי ישיר משאילתות בשפה טבעית לצמתים בגרף באמצעות הטבעות.
|
||||
|
||||
**הצדקה**:
|
||||
מאפשר את הנתיב הפשוט ביותר משאילת NLP לניווט בגרף.
|
||||
נמנע משלבי יצירת שאילתות ביניים מורכבים.
|
||||
מספק יכולות חיפוש סמנטיות יעילות בתוך מבנה הגרף.
|
||||
|
||||
**יישום**:
|
||||
`NLP Query → Graph Embeddings → Graph Nodes`
|
||||
שמירה על ייצוגי הטבעות עבור כל ישויות הגרף.
|
||||
תמיכה בהתאמת דמיון סמנטי ישירה לפתרון שאילתות.
|
||||
|
||||
## יסוד 4: פתרון ישויות מבוזר עם מזהים דטרמיניסטיים
|
||||
**החלטה**: תמיכה בחילוץ ידע מקבילי עם זיהוי ישויות דטרמיניסטי (כלל 80%).
|
||||
|
||||
**הצדקה**:
|
||||
**אידיאלי**: חילוץ בתהליך יחיד עם נראות של מצב מלא מאפשר פתרון ישויות מושלם.
|
||||
**מציאות**: דרישות סקיילביליות מחייבות יכולות עיבוד מקבילי.
|
||||
**פשרה**: תכנון לזיהוי ישויות דטרמיניסטי בכל תהליכים מבוזרים.
|
||||
|
||||
**יישום**:
|
||||
פיתוח מנגנונים ליצירת מזהים עקביים וייחודיים בכל חולצי הידע.
|
||||
אותה ישות המוזכרת בתהליכים שונים חייבת להתפרש לאותו מזהה.
|
||||
יש להכיר בכך ש~20% מהמקרים המיוחדים עשויים לדרוש מודלי עיבוד חלופיים.
|
||||
תכנון מנגנוני ברירת מחדל עבור תרחישי פתרון ישויות מורכבים.
|
||||
|
||||
## יסוד 5: ארכיטקטורה מונעת אירועים עם פרסום-מנוי
|
||||
**החלטה**: יישום מערכת הודעות מבוססת פרסום-מנוי לתיאום מערכות.
|
||||
|
||||
**הצדקה**:
|
||||
מאפשר צימוד רופף בין רכיבי חילוץ, אחסון ושאילתות ידע.
|
||||
תומך בעדכונים והתראות בזמן אמת ברחבי המערכת.
|
||||
מקל על זרימות עבודה מבוזרות וניתנות להרחבה.
|
||||
|
||||
**יישום**:
|
||||
תיאום מונחה הודעות בין רכיבי מערכת.
|
||||
זרמי אירועים לעדכוני ידע, השלמת חילוץ ושליחת תוצאות שאילתות.
|
||||
|
||||
## יסוד 6: תקשורת סוכנים חוזרת
|
||||
**החלטה**: תמיכה בפעולות פרסום-מנוי חוזרות לעיבוד מבוסס סוכנים.
|
||||
|
||||
**הצדקה**:
|
||||
מאפשר זרימות עבודה מורכבות של סוכנים שבהם סוכנים יכולים להפעיל ולהגיב זה לזה.
|
||||
תומך בצינורות עיבוד ידע מורכבים, רב-שלביים.
|
||||
מאפשר דפוסי עיבוד רקורסיביים ואיטרטיביים.
|
||||
|
||||
**יישום**:
|
||||
מערכת הפרסום-מנוי חייבת לטפל בשיחות חוזרות בצורה בטוחה.
|
||||
מנגנוני תיאום סוכנים שמונעים לולאות אינסופיות.
|
||||
תמיכה בתיאום זרימות עבודה של סוכנים.
|
||||
|
||||
## יסוד 7: שילוב עם חנות נתונים טבלאית
|
||||
**החלטה**: הבטחת תאימות שאילתות למערכות אחסון טבלאיות.
|
||||
|
||||
**הצדקה**:
|
||||
מאפשר שאילתות אנליטיות יעילות על פני מערכי ידע גדולים.
|
||||
תומך במקרי שימוש של מודיעין עסקי ודיווח.
|
||||
גשר בין ייצוג ידע מבוסס גרף לבין זרימות עבודה אנליטיות מסורתיות.
|
||||
|
||||
**יישום**:
|
||||
שכבת תרגום שאילתות: שאילתות גרף → שאילתות טבלאיות.
|
||||
אסטרטגיית אחסון היברידית התומכת הן בפעולות גרף והן בעומסי עבודה אנליטיים.
|
||||
שמירה על ביצועי שאילתות בשני הפרדיגמות.
|
||||
|
||||
--
|
||||
|
||||
## סיכום עקרונות ארכיטקטורה
|
||||
|
||||
1. **גמישות ראשית**: מודל SPO/RDF מספק יכולת הסתגלות מרבית.
|
||||
2. **אופטימיזציה ל-LLM**: כל החלטות התכנון מתייחסות לאינטראקציה עם LLM.
|
||||
3. **ניווט יעיל**: שימוש בטבעות (Embeddings) לניווט יעיל בגרף.
|
||||
4. **פתרון ישויות מבוזר**: תמיכה בחילוץ ידע מקבילי עם מזהים דטרמיניסטיים.
|
||||
5. **תיאום מערכות**: שימוש במערכת הודעות מבוססת פרסום-מנוי.
|
||||
6. **עיבוד סוכנים חוזר**: תמיכה בפעולות פרסום-מנוי חוזרות לעיבוד מבוסס סוכנים.
|
||||
7. **תאימות שאילתות**: הבטחת תאימות שאילתות למערכות אחסון טבלאיות.
|
||||
|
||||
יסודות אלה מציבים ארכיטקטורת גרף ידע המאזנת בין דיוק תיאורטי לדרישות מדרגיות מעשיות, ומותאמת לאינטגרציה עם מודלי שפה גדולים (LLM) ולעיבוד מבוזר.
|
||||
113
docs/tech-specs/architecture-principles.hi.md
Normal file
113
docs/tech-specs/architecture-principles.hi.md
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
layout: default
|
||||
title: "नॉलेज ग्राफ आर्किटेक्चर फाउंडेशन"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# नॉलेज ग्राफ आर्किटेक्चर फाउंडेशन
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## फाउंडेशन 1: सब्जेक्ट-प्रेडिकेट-ऑब्जेक्ट (एसपीओ) ग्राफ मॉडल
|
||||
**निर्णय**: एस.पी.ओ./आर.डी.एफ. को मुख्य नॉलेज रिप्रेजेंटेशन मॉडल के रूप में अपनाएं
|
||||
|
||||
**तर्क**:
|
||||
यह अधिकतम लचीलापन और मौजूदा ग्राफ तकनीकों के साथ इंटरऑपरेबिलिटी प्रदान करता है।
|
||||
यह अन्य ग्राफ क्वेरी भाषाओं (जैसे, एस.पी.ओ. → साइफर, लेकिन इसके विपरीत नहीं) में सहज अनुवाद को सक्षम बनाता है।
|
||||
यह एक ऐसा आधार बनाता है जो "बहुत सारी" डाउनस्ट्रीम क्षमताओं को "अनलॉक" करता है।
|
||||
यह नोड-टू-नोड संबंधों (एस.पी.ओ.) और नोड-टू-लिटरल संबंधों (आर.डी.एफ.) दोनों का समर्थन करता है।
|
||||
|
||||
**कार्यान्वयन**:
|
||||
मुख्य डेटा संरचना: `node → edge → {node | literal}`
|
||||
विस्तारित एस.पी.ओ. ऑपरेशनों का समर्थन करते हुए आर.डी.एफ. मानकों के साथ अनुकूलता बनाए रखें।
|
||||
|
||||
## फाउंडेशन 2: एलएलएम-नेटिव नॉलेज ग्राफ इंटीग्रेशन
|
||||
**निर्णय**: एलएलएम इंटरैक्शन के लिए नॉलेज ग्राफ संरचना और ऑपरेशनों को अनुकूलित करें
|
||||
|
||||
**तर्क**:
|
||||
प्राथमिक उपयोग मामला एलएलएम का नॉलेज ग्राफ के साथ इंटरफेस करना है।
|
||||
ग्राफ तकनीक विकल्पों को अन्य विचारों की तुलना में एलएलएम अनुकूलता को प्राथमिकता देनी चाहिए।
|
||||
यह प्राकृतिक भाषा प्रसंस्करण वर्कफ़्लो को संरचित ज्ञान का लाभ उठाने में सक्षम बनाता है।
|
||||
|
||||
**कार्यान्वयन**:
|
||||
ऐसे ग्राफ स्कीमा डिज़ाइन करें जिन्हें एलएलएम प्रभावी ढंग से तर्क दे सकें।
|
||||
सामान्य एलएलएम इंटरैक्शन पैटर्न के लिए अनुकूलित करें।
|
||||
|
||||
## फाउंडेशन 3: एम्बेडिंग-आधारित ग्राफ नेविगेशन
|
||||
**निर्णय**: प्राकृतिक भाषा प्रश्नों को एम्बेडिंग के माध्यम से ग्राफ नोड्स पर सीधे मैप करें
|
||||
|
||||
**तर्क**:
|
||||
यह एनएलपी क्वेरी से ग्राफ नेविगेशन के लिए सबसे सरल पथ को सक्षम करता है।
|
||||
जटिल मध्यवर्ती क्वेरी पीढ़ी चरणों से बचें।
|
||||
ग्राफ संरचना के भीतर कुशल सिमेंटिक खोज क्षमताओं को प्रदान करता है।
|
||||
|
||||
**कार्यान्वयन**:
|
||||
`NLP Query → Graph Embeddings → Graph Nodes`
|
||||
सभी ग्राफ एंटिटीज के लिए एम्बेडिंग रिप्रेजेंटेशन बनाए रखें।
|
||||
क्वेरी रिज़ॉल्यूशन के लिए प्रत्यक्ष सिमेंटिक समानता मिलान का समर्थन करें।
|
||||
|
||||
## फाउंडेशन 4: डिस्ट्रीब्यूटेड एंटिटी रिज़ॉल्यूशन विद डिटर्मिनिस्टिक आइडेंटिफायर्स
|
||||
**निर्णय**: डिस्ट्रीब्यूटेड एंटिटी आइडेंटिफिकेशन (80% नियम) के साथ समानांतर नॉलेज एक्सट्रैक्शन का समर्थन करें
|
||||
|
||||
**तर्क**:
|
||||
**आदर्श**: पूर्ण राज्य दृश्यता के साथ सिंगल-प्रोसेस एक्सट्रैक्शन सही एंटिटी रिज़ॉल्यूशन को सक्षम करता है।
|
||||
**वास्तविकता**: स्केलेबिलिटी आवश्यकताओं के लिए समानांतर प्रसंस्करण क्षमताओं की आवश्यकता होती है।
|
||||
**समझौता**: वितरित प्रक्रियाओं में नियतात्मक एंटिटी पहचान के लिए डिज़ाइन करें।
|
||||
|
||||
**कार्यान्वयन**:
|
||||
ऐसे तंत्र विकसित करें जो विभिन्न नॉलेज एक्सट्रैक्टर्स में सुसंगत, अद्वितीय पहचानकर्ता उत्पन्न करते हैं।
|
||||
विभिन्न प्रक्रियाओं में उल्लिखित एक ही एंटिटी को समान पहचानकर्ता पर हल किया जाना चाहिए।
|
||||
इस बात को स्वीकार करें कि ~20% एज केस के लिए वैकल्पिक प्रसंस्करण मॉडल की आवश्यकता हो सकती है।
|
||||
जटिल एंटिटी रिज़ॉल्यूशन परिदृश्यों के लिए फॉलबैक तंत्र डिज़ाइन करें।
|
||||
|
||||
## फाउंडेशन 5: इवेंट-ड्रिवन आर्किटेक्चर विद पब्लिश-सब्सक्राइब
|
||||
**निर्णय**: सिस्टम समन्वय के लिए एक पब-सब मैसेजिंग सिस्टम लागू करें
|
||||
|
||||
**तर्क**:
|
||||
यह नॉलेज एक्सट्रैक्शन, स्टोरेज और क्वेरी घटकों के बीच ढीला युग्मन को सक्षम करता है।
|
||||
यह पूरे सिस्टम में रीयल-टाइम अपडेट और नोटिफिकेशन का समर्थन करता है।
|
||||
यह स्केलेबल, वितरित प्रसंस्करण वर्कफ़्लो को सुविधाजनक बनाता है।
|
||||
|
||||
**कार्यान्वयन**:
|
||||
सिस्टम घटकों के बीच मैसेज-ड्रिवन समन्वय।
|
||||
नॉलेज अपडेट, एक्सट्रैक्शन पूरा होने और क्वेरी परिणामों के लिए इवेंट स्ट्रीम।
|
||||
|
||||
## फाउंडेशन 6: रीएंट्रेंट एजेंट कम्युनिकेशन
|
||||
**निर्णय**: एजेंट-आधारित प्रसंस्करण के लिए रीएंट्रेंट पब-सब ऑपरेशंस का समर्थन करें
|
||||
|
||||
**तर्क**:
|
||||
यह परिष्कृत एजेंट वर्कफ़्लो को सक्षम करता है जहां एजेंट एक-दूसरे को ट्रिगर और प्रतिक्रिया कर सकते हैं।
|
||||
यह जटिल, बहु-चरणीय नॉलेज प्रोसेसिंग पाइपलाइनों का समर्थन करता है।
|
||||
यह पुनरावर्ती और पुनरावृत्त प्रसंस्करण पैटर्न की अनुमति देता है।
|
||||
|
||||
**कार्यान्वयन**:
|
||||
पब-सब सिस्टम को सुरक्षित रूप से रीएंट्रेंट कॉल को संभालना चाहिए।
|
||||
एजेंट समन्वय तंत्र जो अनंत लूप को रोकते हैं।
|
||||
एजेंट वर्कफ़्लो ऑर्केस्ट्रेशन के लिए समर्थन।
|
||||
|
||||
## फाउंडेशन 7: कॉलम डेटा स्टोर इंटीग्रेशन
|
||||
**निर्णय**: कॉलम स्टोरेज सिस्टम के साथ क्वेरी अनुकूलता सुनिश्चित करें
|
||||
|
||||
**तर्क**:
|
||||
यह बड़े नॉलेज डेटासेट पर कुशल विश्लेषणात्मक प्रश्नों को सक्षम करता है।
|
||||
यह बिजनेस इंटेलिजेंस और रिपोर्टिंग उपयोग मामलों का समर्थन करता है।
|
||||
यह ग्राफ-आधारित नॉलेज रिप्रेजेंटेशन को पारंपरिक विश्लेषणात्मक वर्कफ़्लो के साथ जोड़ता है।
|
||||
|
||||
**कार्यान्वयन**:
|
||||
क्वेरी ट्रांसलेशन लेयर: ग्राफ क्वेरी → कॉलम क्वेरी
|
||||
एक हाइब्रिड स्टोरेज रणनीति जो ग्राफ ऑपरेशंस और विश्लेषणात्मक वर्कलोड दोनों का समर्थन करती है।
|
||||
दोनों प्रतिमानों में क्वेरी प्रदर्शन बनाए रखें।
|
||||
|
||||
--
|
||||
|
||||
## आर्किटेक्चर प्रिंसिपल्स समरी
|
||||
|
||||
1. **लचीलापन पहले**: एस.पी.ओ./आर.डी.एफ. मॉडल अधिकतम अनुकूलन क्षमता प्रदान करता है।
|
||||
2. **एलएलएम अनुकूलन**: सभी डिज़ाइन निर्णयों पर एलएलएम इंटरैक्शन आवश्यकताओं पर विचार किया जाता है।
|
||||
3. **सिमेंटिक दक्षता**: इष्टतम क्वेरी प्रदर्शन के लिए प्रत्यक्ष एम्बेडिंग-टू-नोड मैपिंग।
|
||||
4. **व्यावहारिक स्केलेबिलिटी**: सही सटीकता को व्यावहारिक वितरित प्रसंस्करण के साथ संतुलित करें।
|
||||
5. **इवेंट-ड्रिवन समन्वय**: पब-सब ढीला युग्मन और स्केलेबिलिटी को सक्षम करता है।
|
||||
6. **एजेंट-फ्रेंडली**: जटिल, बहु-एजेंट प्रसंस्करण वर्कफ़्लो का समर्थन करें।
|
||||
7. **विश्लेषणात्मक अनुकूलता**: व्यापक क्वेरी के लिए ग्राफ और कॉलम प्रतिमानों को जोड़ें।
|
||||
|
||||
ये फाउंडेशन एक नॉलेज ग्राफ आर्किटेक्चर स्थापित करते हैं जो सैद्धांतिक कठोरता को व्यावहारिक स्केलेबिलिटी आवश्यकताओं के साथ संतुलित करता है, जो एलएलएम एकीकरण और वितरित प्रसंस्करण के लिए अनुकूलित है।
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Knowledge Graph Architecture Foundations"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Knowledge Graph Architecture Foundations
|
||||
|
||||
## Foundation 1: Subject-Predicate-Object (SPO) Graph Model
|
||||
|
|
@ -103,4 +109,3 @@
|
|||
7. **Analytical Compatibility**: Bridge graph and columnar paradigms for comprehensive querying
|
||||
|
||||
These foundations establish a knowledge graph architecture that balances theoretical rigor with practical scalability requirements, optimized for LLM integration and distributed processing.
|
||||
|
||||
|
|
|
|||
113
docs/tech-specs/architecture-principles.pt.md
Normal file
113
docs/tech-specs/architecture-principles.pt.md
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Arquitetura de Grafos de Conhecimento: Fundamentos"
|
||||
parent: "Portuguese (Beta)"
|
||||
---
|
||||
|
||||
# Arquitetura de Grafos de Conhecimento: Fundamentos
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Fundamento 1: Modelo de Grafo Sujeito-Predicado-Objeto (SPO)
|
||||
**Decisão**: Adotar SPO/RDF como o modelo central de representação de conhecimento
|
||||
|
||||
**Justificativa**:
|
||||
- Fornece máxima flexibilidade e interoperabilidade com tecnologias de grafos existentes
|
||||
- Permite a tradução perfeita para outras linguagens de consulta de grafos (por exemplo, SPO → Cypher, mas não o contrário)
|
||||
- Cria uma base que "desbloqueia muitas" capacidades subsequentes
|
||||
- Suporta relacionamentos de nó para nó (SPO) e relacionamentos de nó para literal (RDF)
|
||||
|
||||
**Implementação**:
|
||||
- Estrutura de dados principal: `node → edge → {node | literal}`
|
||||
- Manter a compatibilidade com os padrões RDF, ao mesmo tempo em que suporta operações SPO estendidas
|
||||
|
||||
## Fundamento 2: Integração Nativa de Grafos de Conhecimento com LLMs
|
||||
**Decisão**: Otimizar a estrutura e as operações do grafo de conhecimento para a interação com LLMs
|
||||
|
||||
**Justificativa**:
|
||||
- O caso de uso primário envolve LLMs interagindo com grafos de conhecimento
|
||||
- As escolhas da tecnologia de grafos devem priorizar a compatibilidade com LLMs em vez de outras considerações
|
||||
- Permite fluxos de trabalho de processamento de linguagem natural que aproveitam o conhecimento estruturado
|
||||
|
||||
**Implementação**:
|
||||
- Projetar esquemas de grafo que os LLMs possam entender e usar efetivamente
|
||||
- Otimizar para padrões comuns de interação com LLMs
|
||||
|
||||
## Fundamento 3: Navegação de Grafos Baseada em Incorporações
|
||||
**Decisão**: Implementar um mapeamento direto de consultas de linguagem natural para nós de grafos por meio de incorporações
|
||||
|
||||
**Justificativa**:
|
||||
- Permite o caminho mais simples possível de uma consulta de PNL para a navegação no grafo
|
||||
- Evita etapas complexas de geração de consultas intermediárias
|
||||
- Fornece capacidades de pesquisa semântica eficientes dentro da estrutura do grafo
|
||||
|
||||
**Implementação**:
|
||||
- `NLP Query → Graph Embeddings → Graph Nodes`
|
||||
- Manter representações de incorporação para todas as entidades do grafo
|
||||
- Suporte para correspondência de similaridade semântica direta para a resolução de consultas
|
||||
|
||||
## Fundamento 4: Resolução Distribuída de Entidades com Identificadores Determinísticos
|
||||
**Decisão**: Suportar a extração de conhecimento paralela com identificação determinística de entidades (regra dos 80%)
|
||||
|
||||
**Justificativa**:
|
||||
- **Ideal**: A extração em um único processo com visibilidade completa do estado permite a resolução perfeita de entidades
|
||||
- **Realidade**: Os requisitos de escalabilidade exigem capacidades de processamento paralelo
|
||||
- **Compromisso**: Projetar para identificação determinística de entidades em processos distribuídos
|
||||
|
||||
**Implementação**:
|
||||
- Desenvolver mecanismos para gerar identificadores consistentes e exclusivos em diferentes extratores de conhecimento
|
||||
- A mesma entidade mencionada em processos diferentes deve resolver para o mesmo identificador
|
||||
- Reconhecer que ~20% dos casos extremos podem exigir modelos de processamento alternativos
|
||||
- Projetar mecanismos de fallback para cenários complexos de resolução de entidades
|
||||
|
||||
## Fundamento 5: Arquitetura Orientada a Eventos com Publicação-Subscrição
|
||||
**Decisão**: Implementar um sistema de mensagens pub-sub para a coordenação do sistema
|
||||
|
||||
**Justificativa**:
|
||||
- Permite o acoplamento frouxo entre os componentes de extração, armazenamento e consulta de conhecimento
|
||||
- Suporta atualizações e notificações em tempo real em todo o sistema
|
||||
- Facilita fluxos de trabalho de processamento distribuídos e escaláveis
|
||||
|
||||
**Implementação**:
|
||||
- Coordenação orientada a mensagens entre os componentes do sistema
|
||||
- Streams de eventos para atualizações de conhecimento, conclusão da extração e resultados de consultas
|
||||
|
||||
## Fundamento 6: Comunicação de Agentes Reentrantes
|
||||
**Decisão**: Suportar operações pub-sub reentrantes para o processamento baseado em agentes
|
||||
|
||||
**Justificativa**:
|
||||
- Permite fluxos de trabalho sofisticados de agentes, nos quais os agentes podem acionar e responder uns aos outros
|
||||
- Suporta pipelines complexos de processamento de conhecimento de várias etapas
|
||||
- Permite padrões de processamento recursivos e iterativos
|
||||
|
||||
**Implementação**:
|
||||
- O sistema pub-sub deve lidar com chamadas reentrantes com segurança
|
||||
- Mecanismos de coordenação de agentes que evitam loops infinitos
|
||||
- Suporte para orquestração de fluxos de trabalho de agentes
|
||||
|
||||
## Fundamento 7: Integração com Armazenamento de Dados Colunares
|
||||
**Decisão**: Garantir a compatibilidade das consultas com sistemas de armazenamento colunar.
|
||||
|
||||
**Justificativa**:
|
||||
- Permite consultas analíticas eficientes em grandes conjuntos de dados de conhecimento.
|
||||
- Suporta casos de uso de inteligência de negócios e relatórios.
|
||||
- Integra a representação de conhecimento baseada em grafos com fluxos de trabalho analíticos tradicionais.
|
||||
|
||||
**Implementação**:
|
||||
- Camada de tradução de consultas: Consultas de grafos → Consultas colunares.
|
||||
- Estratégia de armazenamento híbrida que suporta tanto operações de grafos quanto cargas de trabalho analíticas.
|
||||
- Manter o desempenho das consultas em ambos os paradigmas.
|
||||
|
||||
---
|
||||
|
||||
## Resumo dos Princípios da Arquitetura
|
||||
|
||||
1. **Flexibilidade em Primeiro Lugar**: O modelo SPO/RDF fornece a máxima adaptabilidade.
|
||||
2. **Otimização para LLM**: Todas as decisões de design consideram os requisitos de interação com LLM.
|
||||
3. **Eficiência Semântica**: Mapeamento direto de embeddings para nós para desempenho ideal da consulta.
|
||||
4. **Escalabilidade Pragmática**: Equilibrar a precisão perfeita com o processamento distribuído prático.
|
||||
5. **Coordenação Orientada a Eventos**: Pub-sub permite o acoplamento fraco e a escalabilidade.
|
||||
6. **Compatível com Agentes**: Suporta fluxos de trabalho complexos de processamento multi-agentes.
|
||||
7. **Compatibilidade Analítica**: Integra os paradigmas de grafos e colunares para consultas abrangentes.
|
||||
|
||||
Essas bases estabelecem uma arquitetura de grafo de conhecimento que equilibra a rigidez teórica com os requisitos práticos de escalabilidade, otimizada para a integração com LLM e o processamento distribuído.
|
||||
113
docs/tech-specs/architecture-principles.ru.md
Normal file
113
docs/tech-specs/architecture-principles.ru.md
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Основы архитектуры графа знаний"
|
||||
parent: "Russian (Beta)"
|
||||
---
|
||||
|
||||
# Основы архитектуры графа знаний
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Основа 1: Модель графа "Субъект-Предикат-Объект" (SPO)
|
||||
**Решение**: Принять SPO/RDF в качестве основной модели представления знаний.
|
||||
|
||||
**Обоснование**:
|
||||
Обеспечивает максимальную гибкость и совместимость с существующими технологиями графов.
|
||||
Позволяет беспрепятственно переводить в другие языки запросов к графам (например, SPO → Cypher, но не наоборот).
|
||||
Создает основу, которая "открывает множество" возможностей для дальнейшей разработки.
|
||||
Поддерживает как отношения между узлами (SPO), так и отношения между узлами и литералами (RDF).
|
||||
|
||||
**Реализация**:
|
||||
Основная структура данных: `node → edge → {node | literal}`
|
||||
Поддерживать совместимость со стандартами RDF, одновременно поддерживая расширенные операции SPO.
|
||||
|
||||
## Основа 2: Интеграция графа знаний, оптимизированная для LLM
|
||||
**Решение**: Оптимизировать структуру и операции графа знаний для взаимодействия с LLM.
|
||||
|
||||
**Обоснование**:
|
||||
Основной сценарий использования включает взаимодействие LLM с графами знаний.
|
||||
Выбор технологий графов должен отдавать приоритет совместимости с LLM, а не другим соображениям.
|
||||
Обеспечивает потоки обработки естественного языка, использующие структурированные знания.
|
||||
|
||||
**Реализация**:
|
||||
Разрабатывать схемы графов, которые LLM могут эффективно использовать для рассуждений.
|
||||
Оптимизировать для распространенных шаблонов взаимодействия LLM.
|
||||
|
||||
## Основа 3: Навигация по графу на основе встраиваний
|
||||
**Решение**: Реализовать прямое сопоставление между запросами на естественном языке и узлами графа с помощью встраиваний.
|
||||
|
||||
**Обоснование**:
|
||||
Обеспечивает самый простой путь от запроса на естественном языке к навигации по графу.
|
||||
Избегает сложных промежуточных этапов генерации запросов.
|
||||
Предоставляет возможности семантического поиска в структуре графа.
|
||||
|
||||
**Реализация**:
|
||||
`NLP Query → Graph Embeddings → Graph Nodes`
|
||||
Поддерживать представления встраиваний для всех сущностей графа.
|
||||
Поддерживать прямое семантическое сопоставление сходства для разрешения запросов.
|
||||
|
||||
## Основа 4: Распределенное разрешение сущностей с детерминированными идентификаторами
|
||||
**Решение**: Поддерживать параллельное извлечение знаний с детерминированной идентификацией сущностей (правило 80%).
|
||||
|
||||
**Обоснование**:
|
||||
**Идеально**: Извлечение в одном процессе с полной видимостью состояния обеспечивает идеальное разрешение сущностей.
|
||||
**Реальность**: Требования к масштабируемости требуют возможностей параллельной обработки.
|
||||
**Компромисс**: Разработать для детерминированной идентификации сущностей в распределенных процессах.
|
||||
|
||||
**Реализация**:
|
||||
Разработать механизмы для генерации согласованных, уникальных идентификаторов в различных инструментах извлечения знаний.
|
||||
Одна и та же сущность, упомянутая в разных процессах, должна разрешаться в один и тот же идентификатор.
|
||||
Признать, что ~20% крайних случаев могут потребовать альтернативных моделей обработки.
|
||||
Разработать механизмы отката для сложных сценариев разрешения сущностей.
|
||||
|
||||
## Основа 5: Архитектура, управляемая событиями, с публикацией и подпиской
|
||||
**Решение**: Реализовать систему обмена сообщениями pub-sub для координации системы.
|
||||
|
||||
**Обоснование**:
|
||||
Обеспечивает слабую связанность между компонентами извлечения знаний, хранения и запросов.
|
||||
Поддерживает обновления в режиме реального времени и уведомления по всей системе.
|
||||
Облегчает масштабируемые, распределенные рабочие процессы.
|
||||
|
||||
**Реализация**:
|
||||
Координация между компонентами системы с помощью управляемых сообщениями.
|
||||
Потоки событий для обновлений знаний, завершения извлечения и результатов запросов.
|
||||
|
||||
## Основа 6: Взаимодействие агентов с возможностью повторного входа
|
||||
**Решение**: Поддерживать операции pub-sub с возможностью повторного входа для обработки на основе агентов.
|
||||
|
||||
**Обоснование**:
|
||||
Позволяет создавать сложные рабочие процессы агентов, в которых агенты могут инициировать и реагировать друг на друга.
|
||||
Поддерживает сложные, многоступенчатые конвейеры обработки знаний.
|
||||
Позволяет использовать рекурсивные и итеративные шаблоны обработки.
|
||||
|
||||
**Реализация**:
|
||||
Система pub-sub должна безопасно обрабатывать вызовы с повторным входом.
|
||||
Механизмы координации агентов, предотвращающие бесконечные циклы.
|
||||
Поддержка оркестровки рабочих процессов агентов.
|
||||
|
||||
## Основа 7: Интеграция с хранилищем данных в столбцовом формате
|
||||
**Решение**: Обеспечить совместимость запросов с системами хранения данных в столбцовом формате.
|
||||
|
||||
**Обоснование**:
|
||||
Обеспечивает эффективные аналитические запросы к большим наборам данных знаний.
|
||||
Поддерживает сценарии бизнес-аналитики и отчетности.
|
||||
Объединяет представление знаний на основе графов с традиционными аналитическими рабочими процессами.
|
||||
|
||||
**Реализация**:
|
||||
Слой перевода запросов: Запросы графов → Запросы в столбцовом формате.
|
||||
Гибридная стратегия хранения, поддерживающая как операции графов, так и аналитические рабочие нагрузки.
|
||||
Поддерживать производительность запросов в обеих парадигмах.
|
||||
|
||||
--
|
||||
|
||||
## Краткое изложение принципов архитектуры
|
||||
|
||||
1. **Гибкость прежде всего**: Модель SPO/RDF обеспечивает максимальную адаптируемость.
|
||||
2. **Оптимизация для LLM**: Все решения в области проектирования учитывают требования взаимодействия с LLM.
|
||||
3. **Семантическая эффективность**: Прямое сопоставление встраиваний с узлами для оптимальной производительности запросов.
|
||||
4. **Прагматическая масштабируемость**: Баланс между идеальной точностью и практическими возможностями распределенной обработки.
|
||||
5. **Координация, управляемая событиями**: Pub-sub обеспечивает слабую связанность и масштабируемость.
|
||||
6. **Поддержка агентов**: Поддержка сложных рабочих процессов, основанных на нескольких агентах.
|
||||
7. **Совместимость с аналитикой**: Объединение парадигм графов и столбцов для всестороннего запроса.
|
||||
|
||||
Эта архитектура графа знаний сочетает теоретическую строгость с практическими требованиями масштабируемости, оптимизированная для интеграции с LLM и распределенной обработки.
|
||||
113
docs/tech-specs/architecture-principles.sw.md
Normal file
113
docs/tech-specs/architecture-principles.sw.md
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Msingi wa Usanifu wa Grafu ya Maarifa"
|
||||
parent: "Swahili (Beta)"
|
||||
---
|
||||
|
||||
# Msingi wa Usanifu wa Grafu ya Maarifa
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Msingi wa 1: Mfumo wa Grafu wa Mada-Kitendawili-Jambo (SPO)
|
||||
**Uamuzi**: Kubali SPO/RDF kama mfumo mkuu wa uwakilishi wa maarifa
|
||||
|
||||
**Sababu**:
|
||||
Hutoa uwezekano mwingi na utangamano na teknolojia za grafu zilizopo
|
||||
Inawezesha tafsiri rahisi kwa lugha zingine za kuuliza grafu (e.g., SPO → Cypher, lakini si kinyume chake)
|
||||
Huunda msingi ambao "unawezesha mengi" ya uwezo wa baadaye
|
||||
Inasaidia uhusiano wa kutoka-kwenye-node (SPO) na uhusiano wa kutoka-kwenye-jambo (RDF)
|
||||
|
||||
**Utendaji**:
|
||||
Muundo mkuu wa data: `node → edge → {node | literal}`
|
||||
Endelea utangamano na viwango vya RDF huku ukiunga mkono operesheni zilizopanuliwa za SPO
|
||||
|
||||
## Msingi wa 2: Uunganishaji wa Asili wa Grafu ya Maarifa na LLM
|
||||
**Uamuzi**: Boresha muundo na operesheni za grafu ya maarifa ili kuendana na mwingiliano wa LLM
|
||||
|
||||
**Sababu**:
|
||||
Matumizi kuu yanahusisha LLM zinazofanya kazi na grafu za maarifa
|
||||
Chaguo za teknolojia za grafu lazima zipende utangamano wa LLM kuliko mambo mengine
|
||||
Inawezesha mchakato wa usindikaji wa lugha ya asili ambao hutumia maarifa yaliyopangwa
|
||||
|
||||
**Utendaji**:
|
||||
Unda schema za grafu ambazo LLM zinaweza kuzielewa vizuri
|
||||
Boresha kwa mifumo ya kawaida ya mwingiliano wa LLM
|
||||
|
||||
## Msingi wa 3: Uramaji wa Grafu kwa Kutumia Uingizwaji
|
||||
**Uamuzi**: Tengeneza uhusiano wa moja kwa moja kutoka maswali ya lugha ya asili hadi node za grafu kupitia uingizwaji
|
||||
|
||||
**Sababu**:
|
||||
Inawezesha njia rahisi iwezekanavyo kutoka swali la NLP hadi uramaji wa grafu
|
||||
Inazuia hatua ngumu za kati za kuunda swali
|
||||
Hutoa uwezo wa utafutaji wa kiufundi ndani ya muundo wa grafu
|
||||
|
||||
**Utendaji**:
|
||||
`NLP Query → Graph Embeddings → Graph Nodes`
|
||||
Endelea uwakilishi wa uingizwaji kwa vyombo vyote vya grafu
|
||||
Unga mlingano wa moja kwa moja wa kiufundi kwa utatuzi wa swali
|
||||
|
||||
## Msingi wa 4: Utatuzi Ulio Msingi wa Vitambulisho vya Ufafu na Ufumbuzi Ulio Msingi wa Vitambulisho
|
||||
**Uamuzi**: Unga uongezaji wa maarifa kwa usindikaji sambamba kwa kutumia utambulisho wa vitu vya ufafu (kanuni ya 80%)
|
||||
|
||||
**Sababu**:
|
||||
**Lengo**: Uongezaji wa mchakato mmoja kwa hali kamili unawezesha utatuzi kamili wa vitu
|
||||
**Ukwereti**: Mahitaji ya uongezaji yanahitaji uwezo wa usindikaji sambamba
|
||||
**Suluhisho la Kompromi**: Unda kwa utambulisho wa vitu vya ufafu katika mchakato uliogawanyika
|
||||
|
||||
**Utendaji**:
|
||||
Unda mitambo ya kuzalisha vitambulisho sawa na vya kipekee katika viboreshaji tofauti vya maarifa
|
||||
Kitu kimoja kinachotajwa katika mchakato tofauti lazima kiwe na kitambulisho kimoja
|
||||
Amini kwamba ~20% ya hali ngumu zinaweza kuhitaji modeli zingine za usindikaji
|
||||
Unda mitambo ya dharura kwa hali ngumu za utatuzi wa vitu
|
||||
|
||||
## Msingi wa 5: Usanifu Ulioendeshwa na Tukio na Uchukuzi-Ulisikilizaji
|
||||
**Uamuzi**: Tengeneza mfumo wa ujumbe wa pub-sub kwa upangaji wa mfumo
|
||||
|
||||
**Sababu**:
|
||||
Inawezesha kuunganishwa kwa huru kati ya uongezaji wa maarifa, uhifadhi, na vipengele vya kuuliza
|
||||
Inasaidia sasisho na arifa za wakati halisi katika mfumo
|
||||
Inawezesha mchakato wa usindikaji uliogawanyika na unaoweza kupanuka
|
||||
|
||||
**Utendaji**:
|
||||
Uunganisho uliodumishwa na ujumbe kati ya vipengele vya mfumo
|
||||
Mito ya matukio kwa sasisho za maarifa, kukamilika kwa uongezaji, na matokeo ya kuuliza
|
||||
|
||||
## Msingi wa 6: Mawasiliano ya Wakala wa Kurejea
|
||||
**Uamuzi**: Unga operesheni za pub-sub za kurejea kwa usindikaji wa wakala
|
||||
|
||||
**Sababu**:
|
||||
Inawezesha mchakato wa wakala wa hali ya juu ambapo wakala wanaweza kuchochea na kujibu kila mmoja
|
||||
Inasaidia njia ngumu za usindikaji wa maarifa
|
||||
Inaruhusu mifumo ya usindikaji ya kurudia na ya mara kwa mara
|
||||
|
||||
**Utendaji**:
|
||||
Mfumo wa pub-sub lazima uweze kushughulikia simu za kurejea kwa usalama
|
||||
Mitambo ya upangaji wa wakala ambayo inazuia mzunguko usio na mwisho
|
||||
Usaidizi wa upangaji wa mchakato wa wakala
|
||||
|
||||
## Msingi wa 7: Uunganishaji wa Duka la Data ya Safu
|
||||
**Uamuzi**: Hakikisha utangamano wa kuuliza na mifumo ya uhifadhi wa safu
|
||||
|
||||
**Sababu**:
|
||||
Inawezesha maswali ya uchambuzi ya ufanisi juu ya data kubwa ya maarifa
|
||||
Inasaidia matumizi ya biashara ya ujasusi na ripoti
|
||||
Huunganisha uwakilishi wa maarifa ya grafu na mchakato wa uchambuzi wa jadi
|
||||
|
||||
**Utendaji**:
|
||||
Safu ya tafsiri ya kuuliza: Maswali ya grafu → Maswali ya safu
|
||||
Mkakati wa uhifadhi wa mchanganyiko unaounga mkono operesheni za grafu na mizigo ya uchambuzi
|
||||
Endelea utendaji wa kuuliza katika pande zote
|
||||
|
||||
--
|
||||
|
||||
## Muhtasari wa Kanuni za Usanifu
|
||||
|
||||
1. **Uwezekano Kwanza**: Mfumo wa SPO hutoa uwezekano mwingi
|
||||
2. **Uongezaji wa LLM**: Maamuzi yote ya usanifu yanafikiria mahitaji ya mwingiliano wa LLM
|
||||
3. **Ufanisi wa Kiufundi**: Uramaji wa moja kwa moja wa uingizwaji hadi node kwa utendaji bora wa swali
|
||||
4. **Uongezaji wa Kimapokeo**: Panga usahihi kamili na uwezo wa usindikaji uliogawanyika
|
||||
5. **Usaidizi wa Vitambulisho**: Ufafu wa vitu na utatuzi wa vitu
|
||||
6. **Mawasiliano ya Wakala**: Usaidizi wa mchakato wa wakala
|
||||
7. **Uunganishaji wa Duka la Data**: Usaidizi wa maswali ya uchambuzi
|
||||
|
||||
Misingi hizi huunda usanifu wa mfumo wa kujua ambao unachanganua umakini wa kinadharia na mahitaji ya utendakazi, ukiwa umeboreshwa kwa ajili ya ujumuishaji wa LLM na usindikaji ulioenelea.
|
||||
113
docs/tech-specs/architecture-principles.tr.md
Normal file
113
docs/tech-specs/architecture-principles.tr.md
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Bilgi Grafiği Mimarisi Temelleri"
|
||||
parent: "Turkish (Beta)"
|
||||
---
|
||||
|
||||
# Bilgi Grafiği Mimarisi Temelleri
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Temel 1: Özne-Yüklem-Nesne (ÖYY) Grafik Modeli
|
||||
**Karar**: Çekirdek bilgi gösterim modeli olarak SPO/RDF'yi benimse
|
||||
|
||||
**Gerekçe**:
|
||||
- Mevcut grafik teknolojileriyle maksimum esneklik ve uyumluluk sağlar
|
||||
- Diğer grafik sorgu dillerine (örneğin, SPO → Cypher, ancak tersi değil) sorunsuz çeviri sağlar
|
||||
- "Birçok" sonraki yeteneği "açığa çıkaran" bir temel oluşturur
|
||||
- Hem düğüm-düğüm ilişkilerini (ÖYY) hem de düğüm-literal ilişkilerini (RDF) destekler
|
||||
|
||||
**Uygulama**:
|
||||
- Temel veri yapısı: `node → edge → {node | literal}`
|
||||
- RDF standartlarıyla uyumluluğu korurken, gelişmiş SPO işlemlerini destekler
|
||||
|
||||
## Temel 2: LLM-Yerel Bilgi Grafiği Entegrasyonu
|
||||
**Karar**: Bilgi grafiği yapısını ve işlemlerini LLM etkileşimi için optimize et
|
||||
|
||||
**Gerekçe**:
|
||||
- Birincil kullanım durumu, LLM'lerin bilgi grafikleriyle etkileşimini içerir
|
||||
- Grafik teknolojisi seçimleri, diğer hususlara kıyasla LLM uyumluluğuna öncelik vermelidir
|
||||
- Yapılandırılmış bilgiyi kullanan doğal dil işleme iş akışlarını sağlar
|
||||
|
||||
**Uygulama**:
|
||||
- LLM'lerin etkili bir şekilde akıl yürütebileceği grafik şemalarını tasarla
|
||||
- Yaygın LLM etkileşim kalıpları için optimize et
|
||||
|
||||
## Temel 3: Gömme Tabanlı Grafik Navigasyonu
|
||||
**Karar**: Doğal dil sorgularını, gömmeler aracılığıyla doğrudan grafik düğümlerine eşleyin
|
||||
|
||||
**Gerekçe**:
|
||||
- NLP sorgusundan grafik navigasyonuna en basit yolu sağlar
|
||||
- Karmaşık ara sorgu oluşturma adımlarından kaçının
|
||||
- Grafik yapısı içinde verimli semantik arama yetenekleri sağlar
|
||||
|
||||
**Uygulama**:
|
||||
- `NLP Query → Graph Embeddings → Graph Nodes`
|
||||
- Tüm grafik varlıkları için gömme gösterimlerini koru
|
||||
- Sorgu çözümlemesi için doğrudan semantik benzerlik eşleştirmesini destekle
|
||||
|
||||
## Temel 4: Dağıtılmış Varlık Çözümlemesi ve Belirleyici Tanımlayıcılar
|
||||
**Karar**: Paralel bilgi çıkarma işlemini, deterministik varlık tanımlamasıyla (80% kuralı) destekle
|
||||
|
||||
**Gerekçe**:
|
||||
- **İdeal**: Tam durum görünürlüğü sağlayan tek işlem çıkarma, mükemmel varlık çözümlemesine olanak tanır
|
||||
- **Gerçeklik**: Ölçeklenebilirlik gereksinimleri, paralel işleme yetenekleri gerektirir
|
||||
- **Uzlaşma**: Dağıtılmış işlemler arasında deterministik varlık tanımlaması için tasarla
|
||||
|
||||
**Uygulama**:
|
||||
- Farklı bilgi çıkarıcılar arasında tutarlı, benzersiz tanımlayıcılar oluşturmak için mekanizmalar geliştir
|
||||
- Farklı işlemlerde bahsedilen aynı varlık, aynı tanımlayıcıya çözümlenmelidir
|
||||
- Yaklaşık olarak %20'lik bir oranın, alternatif işleme modelleri gerektirebilecek uç durumlara karşılık geldiğinin farkında olun
|
||||
- Karmaşık varlık çözümleme senaryoları için yedek mekanizmalar tasarla
|
||||
|
||||
## Temel 5: Yayın-Abonelik ile Olay Odaklı Mimari
|
||||
**Karar**: Sistem koordinasyonu için bir yayın-abone mesajlaşma sistemi uygula
|
||||
|
||||
**Gerekçe**:
|
||||
- Bilgi çıkarma, depolama ve sorgu bileşenleri arasında gevşek bir bağlama olanak tanır
|
||||
- Sistem genelinde gerçek zamanlı güncellemeleri ve bildirimleri destekler
|
||||
- Ölçeklenebilir, dağıtılmış iş akışlarını kolaylaştırır
|
||||
|
||||
**Uygulama**:
|
||||
- Sistem bileşenleri arasındaki mesaj odaklı koordinasyon
|
||||
- Bilgi güncellemeleri, çıkarma tamamlama ve sorgu sonuçları için olay akışları
|
||||
|
||||
## Temel 6: Geri Çağrılabilir Ajan İletişimi
|
||||
**Karar**: Ajan tabanlı işleme için geri çağrılabilir yayın-abone işlemlerini destekle
|
||||
|
||||
**Gerekçe**:
|
||||
- Ajanların birbirini tetikleyebildiği ve yanıtlayabildiği gelişmiş ajan iş akışlarına olanak tanır
|
||||
- Karmaşık, çok aşamalı bilgi işleme boru hatlarını destekler
|
||||
- Yinelemeli ve yinelemeli işleme kalıplarına izin verir
|
||||
|
||||
**Uygulama**:
|
||||
- Yayın-abone sistemi, geri çağrılabilir çağrıları güvenli bir şekilde işlemelidir
|
||||
- Sonsuz döngüleri önleyen ajan koordinasyon mekanizmaları
|
||||
- Ajan iş akışı orkestrasyonu desteği
|
||||
|
||||
## Temel 7: Sütun Veri Depolama Entegrasyonu
|
||||
**Karar**: Sorgu uyumluluğunun, sütunlu depolama sistemleriyle sağlanması.
|
||||
|
||||
**Gerekçe**:
|
||||
- Büyük bilgi veri kümeleri üzerinde verimli analitik sorgulara olanak tanır.
|
||||
- İş zekası ve raporlama kullanım senaryolarını destekler.
|
||||
- Grafik tabanlı bilgi gösterimini geleneksel analitik iş akışlarıyla birleştirir.
|
||||
|
||||
**Uygulama**:
|
||||
- Sorgu çevirme katmanı: Grafik sorguları → Sütunlu sorgular.
|
||||
- Hem grafik işlemlerini hem de analitik iş yüklerini destekleyen hibrit depolama stratejisi.
|
||||
- Her iki paradigma için de sorgu performansını koruyun.
|
||||
|
||||
---
|
||||
|
||||
## Mimari İlkeler Özeti
|
||||
|
||||
1. **Öncelikli Olarak Esneklik**: SPO/RDF modeli, maksimum uyarlanabilirlik sağlar.
|
||||
2. **LLM Optimizasyonu**: Tüm tasarım kararları, LLM etkileşim gereksinimlerini dikkate alır.
|
||||
3. **Anlamsal Verimlilik**: Optimum sorgu performansı için doğrudan gömülü-düğüm eşlemesi.
|
||||
4. **Pratik Ölçeklenebilirlik**: Mükemmel doğruluğu, pratik dağıtılmış işleme ile dengeleyin.
|
||||
5. **Olay Odaklı Koordinasyon**: Yayın-abone, gevşek bağlama ve ölçeklenebilirliğe olanak tanır.
|
||||
6. **Ajan Dostu**: Karmaşık, çoklu ajan iş akışlarını destekler.
|
||||
7. **Analitik Uyumluluk**: Kapsamlı sorgulama için grafik ve sütunlu paradigmaları birleştirir.
|
||||
|
||||
Bu temeller, teorik titizliği pratik ölçeklenebilirlik gereksinimleriyle dengeleyen, LLM entegrasyonu ve dağıtılmış işleme için optimize edilmiş bir bilgi grafiği mimarisi oluşturur.
|
||||
135
docs/tech-specs/architecture-principles.zh-cn.md
Normal file
135
docs/tech-specs/architecture-principles.zh-cn.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
layout: default
|
||||
title: "知识图谱架构基础"
|
||||
parent: "Chinese (Beta)"
|
||||
---
|
||||
|
||||
# 知识图谱架构基础
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## 基础 1:主谓宾 (SPO) 图模型
|
||||
**决策**: 采用 SPO/RDF 作为核心知识表示模型
|
||||
|
||||
**理由**:
|
||||
提供最大的灵活性和与现有图技术的互操作性
|
||||
能够无缝转换为其他图查询语言 (例如,SPO → Cypher,反之则不行)
|
||||
奠定基础,"解锁"许多下游功能
|
||||
支持节点到节点的关系 (SPO) 和节点到字面值关系 (RDF)
|
||||
|
||||
**实施**:
|
||||
核心数据结构: `node → edge → {node | literal}`
|
||||
在支持扩展的 SPO 操作的同时,保持与 RDF 标准的兼容性
|
||||
|
||||
## 基础 2:原生于 LLM 的知识图谱集成
|
||||
**决策**: 优化知识图谱结构和操作,以实现与 LLM 的交互
|
||||
|
||||
**理由**:
|
||||
主要用例涉及 LLM 与知识图谱的交互
|
||||
图技术选择必须优先考虑与 LLM 的兼容性,而不是其他考虑因素
|
||||
能够实现利用结构化知识的自然语言处理工作流程
|
||||
|
||||
**实施**:
|
||||
设计 LLM 可以有效推理的图模式
|
||||
针对常见的 LLM 交互模式进行优化
|
||||
|
||||
## 基础 3:基于嵌入的图导航
|
||||
**决策**: 通过嵌入将自然语言查询直接映射到图节点
|
||||
|
||||
**理由**:
|
||||
实现从 NLP 查询到图导航的最简单路径
|
||||
避免复杂的中间查询生成步骤
|
||||
提供图结构内部高效的语义搜索功能
|
||||
|
||||
**实施**:
|
||||
`NLP Query → Graph Embeddings → Graph Nodes`
|
||||
维护所有图实体的嵌入表示
|
||||
支持用于查询解析的直接语义相似性匹配
|
||||
|
||||
## 基础 4:分布式实体解析与确定性标识符
|
||||
**决策**: 支持并行知识提取,并使用确定性实体标识 (80% 规则)
|
||||
|
||||
**理由**:
|
||||
**理想**: 单进程提取,具有完整的状态可见性,可以实现完美的实体解析
|
||||
<<<<<<< HEAD
|
||||
**现实**: 可扩展性要求需要并行处理能力
|
||||
=======
|
||||
**现实**: 扩展性要求需要并行处理能力
|
||||
>>>>>>> 82edf2d (New md files from RunPod)
|
||||
**折衷**: 设计用于在分布式进程中实现确定性实体标识
|
||||
|
||||
**实施**:
|
||||
开发机制,以生成在不同知识提取器中保持一致且唯一的标识符
|
||||
在不同的进程中提到的相同实体必须解析为相同的标识符
|
||||
承认约 20% 的边缘情况可能需要替代处理模型
|
||||
设计用于处理复杂实体解析场景的后备机制
|
||||
|
||||
## 基础 5:事件驱动架构与发布-订阅
|
||||
<<<<<<< HEAD
|
||||
**决策**: 实施 pub-sub 消息系统,用于系统协调
|
||||
=======
|
||||
**决策**: 实现发布-订阅消息系统,用于系统协调
|
||||
>>>>>>> 82edf2d (New md files from RunPod)
|
||||
|
||||
**理由**:
|
||||
允许知识提取、存储和查询组件之间的松散耦合
|
||||
支持实时更新和跨系统的通知
|
||||
促进可扩展的分布式处理工作流程
|
||||
|
||||
**实施**:
|
||||
使用消息驱动的系统组件协调
|
||||
用于知识更新、提取完成和查询结果的事件流
|
||||
|
||||
## 基础 6:可重入代理通信
|
||||
**决策**: 支持用于基于代理的处理的可重入发布-订阅操作
|
||||
|
||||
**理由**:
|
||||
允许代理触发和响应彼此,从而实现复杂的代理工作流程
|
||||
支持复杂的多步骤知识处理管道
|
||||
允许递归和迭代处理模式
|
||||
|
||||
<<<<<<< HEAD
|
||||
**实施**:
|
||||
pub-sub 系统必须安全地处理可重入调用
|
||||
=======
|
||||
**实现**:
|
||||
发布-订阅系统必须安全地处理可重入调用
|
||||
>>>>>>> 82edf2d (New md files from RunPod)
|
||||
防止无限循环的代理协调机制
|
||||
支持代理工作流程编排
|
||||
|
||||
## 基础 7:列式数据存储集成
|
||||
**决策**: 确保查询与列式存储系统兼容
|
||||
|
||||
**理由**:
|
||||
能够对大型知识数据集执行高效的分析查询
|
||||
支持商业智能和报告用例
|
||||
桥接基于图的知识表示与传统的分析工作流程
|
||||
|
||||
**实施**:
|
||||
查询转换层:图查询 → 列式查询
|
||||
<<<<<<< HEAD
|
||||
支持图操作和分析工作负载的混合存储策略
|
||||
=======
|
||||
混合存储策略,支持图操作和分析工作负载
|
||||
>>>>>>> 82edf2d (New md files from RunPod)
|
||||
在这两种范例中保持查询性能
|
||||
|
||||
--
|
||||
|
||||
## 架构原则摘要
|
||||
|
||||
1. **灵活性至上**: SPO/RDF 模型提供最大的适应性
|
||||
2. **LLM 优化**: 所有设计决策都考虑 LLM 交互要求
|
||||
3. **语义效率**: 直接的嵌入到节点映射,以实现最佳的查询性能
|
||||
<<<<<<< HEAD
|
||||
4. **务实的扩展性**: 在完美准确性和实际的分布式处理之间取得平衡
|
||||
5. **事件驱动协调**: pub-sub 实现松散耦合和可扩展性
|
||||
=======
|
||||
4. **务实的扩展性**: 在完美的准确性与实际的分布式处理之间取得平衡
|
||||
5. **事件驱动协调**: 发布-订阅实现松散耦合和可扩展性
|
||||
>>>>>>> 82edf2d (New md files from RunPod)
|
||||
6. **代理友好**: 支持复杂的多代理处理工作流程
|
||||
7. **分析兼容性**: 桥接图和列式范例,以实现全面的查询
|
||||
|
||||
这些基础构建了一个知识图谱架构,该架构在理论严谨性和实际可扩展性之间取得了平衡,并针对 LLM 集成和分布式处理进行了优化。
|
||||
339
docs/tech-specs/cassandra-consolidation.ar.md
Normal file
339
docs/tech-specs/cassandra-consolidation.ar.md
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
---
|
||||
layout: default
|
||||
title: "مواصفات فنية: توحيد إعدادات Cassandra"
|
||||
parent: "Arabic (Beta)"
|
||||
---
|
||||
|
||||
# مواصفات فنية: توحيد إعدادات Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**الحالة:** مسودة
|
||||
**المؤلف:** مساعد
|
||||
**التاريخ:** 2024-09-03
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
تتناول هذه المواصفة عدم الاتساق في أسماء وأنماط إعدادات معلمات اتصال Cassandra عبر قاعدة بيانات TrustGraph. حاليًا، توجد مخططان مختلفان لتسمية المعلمات (`cassandra_*` مقابل `graph_*`)، مما يؤدي إلى الارتباك وتعقيد الصيانة.
|
||||
|
||||
## بيان المشكلة
|
||||
|
||||
تستخدم قاعدة البيانات حاليًا مجموعتين متميزتين من معلمات إعداد Cassandra:
|
||||
|
||||
1. **وحدات المعرفة/التكوين/المكتبة** تستخدم:
|
||||
`cassandra_host` (قائمة المضيفين)
|
||||
`cassandra_user`
|
||||
`cassandra_password`
|
||||
|
||||
2. **وحدات الرسم البياني/التخزين** تستخدم:
|
||||
`graph_host` (مضيف واحد، يتم تحويله أحيانًا إلى قائمة)
|
||||
`graph_username`
|
||||
`graph_password`
|
||||
|
||||
3. **عرض غير متسق عبر سطر الأوامر**:
|
||||
بعض المعالجات (مثل `kg-store`) لا تعرض إعدادات Cassandra كمعلمات سطر أوامر
|
||||
تعرض معالجات أخرى هذه الإعدادات بأسماء وتنسيقات مختلفة
|
||||
لا يعكس نص المساعدة القيم الافتراضية لمتغيرات البيئة
|
||||
|
||||
تتصل كلتا مجموعتي المعلمات بنفس مجموعة Cassandra ولكن باتفاقيات تسمية مختلفة، مما يسبب:
|
||||
ارتباك في التكوين للمستخدمين
|
||||
زيادة العبء على الصيانة
|
||||
توثيق غير متسق
|
||||
احتمال حدوث سوء تكوين
|
||||
عدم القدرة على تجاوز الإعدادات عبر سطر الأوامر في بعض المعالجات
|
||||
|
||||
## الحل المقترح
|
||||
|
||||
### 1. توحيد أسماء المعلمات
|
||||
|
||||
ستستخدم جميع الوحدات أسماء معلمات متسقة `cassandra_*`:
|
||||
`cassandra_host` - قائمة المضيفين (مخزنة داخليًا كقائمة)
|
||||
`cassandra_username` - اسم المستخدم للمصادقة
|
||||
`cassandra_password` - كلمة المرور للمصادقة
|
||||
|
||||
### 2. معلمات سطر الأوامر
|
||||
|
||||
يجب على جميع المعالجات عرض إعدادات تكوين Cassandra عبر معلمات سطر الأوامر:
|
||||
`--cassandra-host` - قائمة مفصولة بفواصل من المضيفين
|
||||
`--cassandra-username` - اسم المستخدم للمصادقة
|
||||
`--cassandra-password` - كلمة المرور للمصادقة
|
||||
|
||||
### 3. الاعتماد على متغيرات البيئة
|
||||
|
||||
إذا لم يتم توفير معلمات سطر الأوامر بشكل صريح، فسيتحقق النظام من متغيرات البيئة:
|
||||
`CASSANDRA_HOST` - قائمة مفصولة بفواصل من المضيفين
|
||||
`CASSANDRA_USERNAME` - اسم المستخدم للمصادقة
|
||||
`CASSANDRA_PASSWORD` - كلمة المرور للمصادقة
|
||||
|
||||
### 4. القيم الافتراضية
|
||||
|
||||
إذا لم يتم تحديد أي من معلمات سطر الأوامر أو متغيرات البيئة:
|
||||
`cassandra_host` افتراضيًا إلى `["cassandra"]`
|
||||
`cassandra_username` افتراضيًا إلى `None` (بدون مصادقة)
|
||||
`cassandra_password` افتراضيًا إلى `None` (بدون مصادقة)
|
||||
|
||||
### 5. متطلبات نص المساعدة
|
||||
|
||||
يجب أن يعرض الإخراج `--help`:
|
||||
إظهار قيم متغيرات البيئة كقيم افتراضية عند تعيينها
|
||||
عدم عرض قيم كلمات المرور مطلقًا (إظهار `****` أو `<set>` بدلاً من ذلك)
|
||||
الإشارة بوضوح إلى ترتيب الحل في نص المساعدة
|
||||
|
||||
مثال على إخراج المساعدة:
|
||||
```
|
||||
--cassandra-host HOST
|
||||
Cassandra host list, comma-separated (default: prod-cluster-1,prod-cluster-2)
|
||||
[from CASSANDRA_HOST environment variable]
|
||||
|
||||
--cassandra-username USERNAME
|
||||
Cassandra username (default: cassandra_user)
|
||||
[from CASSANDRA_USERNAME environment variable]
|
||||
|
||||
--cassandra-password PASSWORD
|
||||
Cassandra password (default: <set from environment>)
|
||||
```
|
||||
|
||||
## تفاصيل التنفيذ
|
||||
|
||||
### ترتيب حل المعلمات
|
||||
|
||||
لكل معلمة في Cassandra، سيكون ترتيب الحل كما يلي:
|
||||
1. قيمة وسيط سطر الأوامر
|
||||
2. متغير البيئة (`CASSANDRA_*`)
|
||||
3. القيمة الافتراضية
|
||||
|
||||
### معالجة معلمات المضيف
|
||||
|
||||
المعلمة `cassandra_host`:
|
||||
يقبل سطر الأوامر سلسلة مفصولة بفواصل: `--cassandra-host "host1,host2,host3"`
|
||||
يقبل متغير البيئة سلسلة مفصولة بفواصل: `CASSANDRA_HOST="host1,host2,host3"`
|
||||
يتم تخزينها دائمًا داخليًا كقائمة: `["host1", "host2", "host3"]`
|
||||
مضيف واحد: `"localhost"` → يتم تحويله إلى `["localhost"]`
|
||||
إذا كانت بالفعل قائمة: `["host1", "host2"]` → يتم استخدامها كما هي
|
||||
|
||||
### منطق المصادقة
|
||||
|
||||
سيتم استخدام المصادقة عندما يتم توفير كل من `cassandra_username` و `cassandra_password`:
|
||||
```python
|
||||
if cassandra_username and cassandra_password:
|
||||
# Use SSL context and PlainTextAuthProvider
|
||||
else:
|
||||
# Connect without authentication
|
||||
```
|
||||
|
||||
## الملفات المراد تعديلها
|
||||
|
||||
### الوحدات التي تستخدم معلمات `graph_*` (يجب تغييرها):
|
||||
`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/rows/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
|
||||
### الوحدات التي تستخدم معلمات `cassandra_*` (يجب تحديثها مع استخدام الإعدادات الافتراضية للبيئة):
|
||||
`trustgraph-flow/trustgraph/tables/config.py`
|
||||
`trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/tables/library.py`
|
||||
`trustgraph-flow/trustgraph/storage/knowledge/store.py`
|
||||
`trustgraph-flow/trustgraph/cores/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/librarian/librarian.py`
|
||||
`trustgraph-flow/trustgraph/librarian/service.py`
|
||||
`trustgraph-flow/trustgraph/config/service/service.py`
|
||||
`trustgraph-flow/trustgraph/cores/service.py`
|
||||
|
||||
### ملفات الاختبار المراد تحديثها:
|
||||
`tests/unit/test_cores/test_knowledge_manager.py`
|
||||
`tests/unit/test_storage/test_triples_cassandra_storage.py`
|
||||
`tests/unit/test_query/test_triples_cassandra_query.py`
|
||||
`tests/integration/test_objects_cassandra_integration.py`
|
||||
|
||||
## استراتيجية التنفيذ
|
||||
|
||||
### المرحلة الأولى: إنشاء أداة مساعدة للإعدادات المشتركة
|
||||
إنشاء دوال مساعدة لتوحيد إعدادات Cassandra عبر جميع المعالجات:
|
||||
|
||||
```python
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def get_cassandra_defaults():
|
||||
"""Get default values from environment variables or fallback."""
|
||||
return {
|
||||
'host': os.getenv('CASSANDRA_HOST', 'cassandra'),
|
||||
'username': os.getenv('CASSANDRA_USERNAME'),
|
||||
'password': os.getenv('CASSANDRA_PASSWORD')
|
||||
}
|
||||
|
||||
def add_cassandra_args(parser: argparse.ArgumentParser):
|
||||
"""
|
||||
Add standardized Cassandra arguments to an argument parser.
|
||||
Shows environment variable values in help text.
|
||||
"""
|
||||
defaults = get_cassandra_defaults()
|
||||
|
||||
# Format help text with env var indication
|
||||
host_help = f"Cassandra host list, comma-separated (default: {defaults['host']})"
|
||||
if 'CASSANDRA_HOST' in os.environ:
|
||||
host_help += " [from CASSANDRA_HOST]"
|
||||
|
||||
username_help = f"Cassandra username"
|
||||
if defaults['username']:
|
||||
username_help += f" (default: {defaults['username']})"
|
||||
if 'CASSANDRA_USERNAME' in os.environ:
|
||||
username_help += " [from CASSANDRA_USERNAME]"
|
||||
|
||||
password_help = "Cassandra password"
|
||||
if defaults['password']:
|
||||
password_help += " (default: <set>)"
|
||||
if 'CASSANDRA_PASSWORD' in os.environ:
|
||||
password_help += " [from CASSANDRA_PASSWORD]"
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-host',
|
||||
default=defaults['host'],
|
||||
help=host_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-username',
|
||||
default=defaults['username'],
|
||||
help=username_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-password',
|
||||
default=defaults['password'],
|
||||
help=password_help
|
||||
)
|
||||
|
||||
def resolve_cassandra_config(args) -> tuple[list[str], str|None, str|None]:
|
||||
"""
|
||||
Convert argparse args to Cassandra configuration.
|
||||
|
||||
Returns:
|
||||
tuple: (hosts_list, username, password)
|
||||
"""
|
||||
# Convert host string to list
|
||||
if isinstance(args.cassandra_host, str):
|
||||
hosts = [h.strip() for h in args.cassandra_host.split(',')]
|
||||
else:
|
||||
hosts = args.cassandra_host
|
||||
|
||||
return hosts, args.cassandra_username, args.cassandra_password
|
||||
```
|
||||
|
||||
### المرحلة الثانية: تحديث الوحدات باستخدام معلمات `graph_*`
|
||||
1. تغيير أسماء المعلمات من `graph_*` إلى `cassandra_*`
|
||||
2. استبدال طرق `add_args()` المخصصة بطرق `add_cassandra_args()` القياسية
|
||||
3. استخدام الدوال المساعدة الشائعة للتكوين
|
||||
4. تحديث سلاسل التوثيق
|
||||
|
||||
مثال على التحويل:
|
||||
```python
|
||||
# OLD CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
parser.add_argument(
|
||||
'-g', '--graph-host',
|
||||
default="localhost",
|
||||
help=f'Graph host (default: localhost)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--graph-username',
|
||||
default=None,
|
||||
help=f'Cassandra username'
|
||||
)
|
||||
|
||||
# NEW CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
FlowProcessor.add_args(parser)
|
||||
add_cassandra_args(parser) # Use standard helper
|
||||
```
|
||||
|
||||
### المرحلة الثالثة: تحديث الوحدات باستخدام معلمات `cassandra_*`
|
||||
1. إضافة دعم للوسائط الخاصة بسطر الأوامر في الحالات التي تفتقر إليها (مثل: `kg-store`)
|
||||
2. استبدال تعريفات الوسائط الحالية بـ `add_cassandra_args()`
|
||||
3. استخدام `resolve_cassandra_config()` لتحقيق التوافق
|
||||
4. التأكد من معالجة متسقة لقائمة المضيفين
|
||||
|
||||
### المرحلة الرابعة: تحديث الاختبارات والوثائق
|
||||
1. تحديث جميع ملفات الاختبار لاستخدام أسماء المعلمات الجديدة
|
||||
2. تحديث وثائق واجهة سطر الأوامر
|
||||
3. تحديث وثائق واجهة برمجة التطبيقات
|
||||
4. إضافة وثائق لمتغيرات البيئة
|
||||
|
||||
## التوافق مع الإصدارات السابقة
|
||||
|
||||
للحفاظ على التوافق مع الإصدارات السابقة أثناء الانتقال:
|
||||
|
||||
1. **تحذيرات الإيقاف التدريجي** لمعلمات `graph_*`
|
||||
2. **تسمية بديلة للمعلمات** - قبول الأسماء القديمة والجديدة في البداية
|
||||
3. **نشر تدريجي** على مدار عدة إصدارات
|
||||
4. **تحديثات الوثائق** مع دليل الترحيل
|
||||
|
||||
مثال على كود التوافق مع الإصدارات السابقة:
|
||||
```python
|
||||
def __init__(self, **params):
|
||||
# Handle deprecated graph_* parameters
|
||||
if 'graph_host' in params:
|
||||
warnings.warn("graph_host is deprecated, use cassandra_host", DeprecationWarning)
|
||||
params.setdefault('cassandra_host', params.pop('graph_host'))
|
||||
|
||||
if 'graph_username' in params:
|
||||
warnings.warn("graph_username is deprecated, use cassandra_username", DeprecationWarning)
|
||||
params.setdefault('cassandra_username', params.pop('graph_username'))
|
||||
|
||||
# ... continue with standard resolution
|
||||
```
|
||||
|
||||
## استراتيجية الاختبار
|
||||
|
||||
1. **اختبارات الوحدة** لمنطق حل التكوين.
|
||||
2. **اختبارات التكامل** مع مجموعات تكوين مختلفة.
|
||||
3. **اختبارات متغيرات البيئة**.
|
||||
4. **اختبارات التوافق مع الإصدارات السابقة** مع المعلمات التي تم إيقافها.
|
||||
5. **اختبارات Docker Compose** مع متغيرات البيئة.
|
||||
|
||||
## تحديثات التوثيق
|
||||
|
||||
1. تحديث جميع وثائق أوامر واجهة سطر الأوامر.
|
||||
2. تحديث وثائق واجهة برمجة التطبيقات.
|
||||
3. إنشاء دليل ترحيل.
|
||||
4. تحديث أمثلة Docker Compose.
|
||||
5. تحديث وثائق مرجع التكوين.
|
||||
|
||||
## المخاطر والتخفيف
|
||||
|
||||
| المخاطر | التأثير | التخفيف |
|
||||
|------|--------|------------|
|
||||
| تغييرات تؤثر على المستخدمين | مرتفع | تطبيق فترة التوافق مع الإصدارات السابقة. |
|
||||
| ارتباك في التكوين أثناء الانتقال | متوسط | توثيق واضح وتحذيرات إيقاف. |
|
||||
| فشل الاختبارات | متوسط | تحديثات شاملة للاختبارات. |
|
||||
| مشاكل في نشر Docker | مرتفع | تحديث جميع أمثلة Docker Compose. |
|
||||
|
||||
## معايير النجاح
|
||||
|
||||
[ ] تستخدم جميع الوحدات أسماء معلمات `cassandra_*` متسقة.
|
||||
[ ] تعرض جميع المعالجات إعدادات Cassandra عبر وسيطات سطر الأوامر.
|
||||
[ ] يعرض نص المساعدة الخاص بسطر الأوامر القيم الافتراضية لمتغيرات البيئة.
|
||||
[ ] لا يتم عرض قيم كلمات المرور في نص المساعدة.
|
||||
[ ] يعمل التراجع إلى متغيرات البيئة بشكل صحيح.
|
||||
[ ] يتم التعامل مع `cassandra_host` باستمرار كقائمة داخليًا.
|
||||
[ ] تم الحفاظ على التوافق مع الإصدارات السابقة لمدة إصدارين على الأقل.
|
||||
[ ] تجتاز جميع الاختبارات مع نظام التكوين الجديد.
|
||||
[ ] تم تحديث التوثيق بالكامل.
|
||||
[ ] تعمل أمثلة Docker Compose مع متغيرات البيئة.
|
||||
|
||||
## الجدول الزمني
|
||||
|
||||
**الأسبوع 1:** تنفيذ أداة مساعدة شائعة للتكوين وتحديث وحدات `graph_*`.
|
||||
**الأسبوع 2:** إضافة دعم لمتغيرات البيئة إلى وحدات `cassandra_*` الحالية.
|
||||
**الأسبوع 3:** تحديث الاختبارات والتوثيق.
|
||||
**الأسبوع 4:** اختبار التكامل وتصحيح الأخطاء.
|
||||
|
||||
## اعتبارات مستقبلية
|
||||
|
||||
ضع في اعتبارك توسيع هذا النمط ليشمل تكوينات قواعد بيانات أخرى (مثل Elasticsearch).
|
||||
تنفيذ التحقق من صحة التكوين ورسائل خطأ أفضل.
|
||||
إضافة دعم لتكوين تجميع الاتصالات لـ Cassandra.
|
||||
ضع في اعتبارك إضافة دعم لملفات التكوين (ملفات .env).
|
||||
249
docs/tech-specs/cassandra-consolidation.es.md
Normal file
249
docs/tech-specs/cassandra-consolidation.es.md
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificación Técnica: Consolidación de la Configuración de Cassandra"
|
||||
parent: "Spanish (Beta)"
|
||||
---
|
||||
|
||||
# Especificación Técnica: Consolidación de la Configuración de Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**Estado:** Borrador
|
||||
**Autor:** Asistente
|
||||
**Fecha:** 2024-09-03
|
||||
|
||||
## Visión General
|
||||
|
||||
Esta especificación aborda los patrones de nombres y configuración inconsistentes para los parámetros de conexión de Cassandra en todo el código base de TrustGraph. Actualmente, existen dos esquemas de nombres de parámetros diferentes (`cassandra_*` frente a `graph_*`), lo que provoca confusión y complejidad en el mantenimiento.
|
||||
|
||||
## Declaración del Problema
|
||||
|
||||
El código base actualmente utiliza dos conjuntos distintos de parámetros de configuración de Cassandra:
|
||||
|
||||
1. **Módulos de Conocimiento/Config/Biblioteca** utilizan:
|
||||
- `cassandra_host` (lista de hosts)
|
||||
- `cassandra_usuario`
|
||||
- `cassandra_contraseña`
|
||||
|
||||
2. **Módulos de Gráficos/Almacenamiento** utilizan:
|
||||
- `graph_host` (único host, a veces convertido en lista)
|
||||
- `graph_username`
|
||||
- `graph_password`
|
||||
|
||||
3. **Exposición inconsistente de la línea de comandos:**
|
||||
- Algunos procesadores (p. ej., `kg-store`) no expone la configuración de Cassandra como argumentos de línea de comandos
|
||||
- Otros procesadores los expone con nombres y formatos diferentes
|
||||
- El texto de ayuda no refleja los valores predeterminados de las variables de entorno
|
||||
|
||||
Ambos conjuntos de parámetros se conectan al mismo clúster de Cassandra, pero con diferentes convenciones de nombres, lo que provoca:
|
||||
- Confusión en la configuración para los usuarios
|
||||
- Mayor carga de mantenimiento
|
||||
- Documentación inconsistente
|
||||
- Posibilidad de configuración incorrecta
|
||||
- Incapacidad de anular la configuración mediante argumentos de línea de comandos en algunos procesadores
|
||||
|
||||
## Solución Propuesta
|
||||
|
||||
### 1. Estandarizar los Nombres de los Parámetros
|
||||
|
||||
Todos los módulos utilizarán nombres de parámetros consistentes `cassandra_*`:
|
||||
- `cassandra_host` - Lista de hosts (almacenado internamente como lista)
|
||||
- `cassandra_username` - Nombre de usuario para la autenticación
|
||||
- `cassandra_contraseña` - Contraseña para la autenticación
|
||||
|
||||
### 2. Argumentos de Línea de Comandos
|
||||
|
||||
Todos los procesadores DEBEN exponer la configuración de Cassandra a través de argumentos de línea de comandos:
|
||||
- `--cassandra-host` - Lista separada por comas de hosts
|
||||
- `--cassandra-username` - Nombre de usuario para la autenticación
|
||||
- `--cassandra-password` - Contraseña para la autenticación
|
||||
|
||||
### 3. Fallback de Variables de Entorno
|
||||
|
||||
Si los parámetros de la línea de comandos no se proporcionan explícitamente, el sistema verificará las variables de entorno:
|
||||
- `CASSANDRA_HOST` - Lista separada por comas de hosts
|
||||
- `CASSANDRA_USERNAME` - Nombre de usuario para la autenticación
|
||||
- `CASSANDRA_PASSWORD` - Contraseña para la autenticación
|
||||
|
||||
### 4. Valores Predeterminados
|
||||
|
||||
Si ni los parámetros de la línea de comandos ni las variables de entorno no se especifican:
|
||||
- `cassandra_host` se establece en `["cassandra"]`
|
||||
- `cassandra_username` se establece en `None` (sin autenticación)
|
||||
- `cassandra_password` se establece en `None` (sin autenticación)
|
||||
|
||||
### 5. Requisitos de Ayuda
|
||||
|
||||
La salida `--help` DEBE:
|
||||
- Mostrar los valores predeterminados de las variables de entorno
|
||||
- Nunca mostrar los valores de la contraseña (mostrar `****` o `<set>` en su lugar)
|
||||
- Indicar claramente el orden de resolución en la ayuda
|
||||
|
||||
Ejemplo de salida de ayuda:
|
||||
```
|
||||
--cassandra-host HOST
|
||||
Lista de hosts de Cassandra, separada por comas (predeterminado: prod-cluster-1,prod-cluster-2)
|
||||
[desde la variable de entorno CASSANDRA_HOST]
|
||||
|
||||
--cassandra-username USERNAME
|
||||
Nombre de usuario de Cassandra (predeterminado: cassandra_user)
|
||||
[desde la variable de entorno CASSANDRA_USERNAME]
|
||||
|
||||
--cassandra-password PASSWORD
|
||||
Contraseña de Cassandra (predeterminado: <establecido desde el entorno>)
|
||||
```
|
||||
|
||||
## Detalles de Implementación
|
||||
|
||||
### Orden de Resolución
|
||||
Para cada parámetro de Cassandra, el orden de resolución será:
|
||||
1. Valor del argumento de la línea de comandos
|
||||
2. Variable de entorno (`CASSANDRA_*`)
|
||||
3. Valor predeterminado
|
||||
|
||||
### Manejo del parámetro Host
|
||||
El parámetro `cassandra_host`:
|
||||
- La línea de comandos acepta una cadena separada por comas: `--cassandra-host "host1,host2,host3"`
|
||||
- La variable de entorno acepta una cadena separada por comas: `CASSANDRA_HOST="host1,host2,host3"`
|
||||
- Internamente siempre se almacena como una lista: `["host1", "host2", "host3"]`
|
||||
|
||||
### Código de Ejemplo
|
||||
```python
|
||||
# Código antiguo
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
parser.add_argument(
|
||||
'-g', '--graph-host',
|
||||
default="localhost",
|
||||
help='Host del gráfico (predeterminado: localhost)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--graph-username',
|
||||
default=None,
|
||||
help='Nombre de usuario de Cassandra'
|
||||
)
|
||||
|
||||
# Código nuevo
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
FlowProcessor.add_args(parser)
|
||||
add_cassandra_args(parser) # Usa el asistente estándar
|
||||
```
|
||||
|
||||
### Actualización de Módulos que Utilizan `graph_*` Parámetros
|
||||
1. Cambiar los nombres de los parámetros de `graph_*` a `cassandra_*`
|
||||
2. Reemplazar los métodos `add_args()` personalizados
|
||||
3. Utilizar las funciones `add_cassandra_args()` estándar
|
||||
4. Actualizar las cadenas de documentación
|
||||
|
||||
Ejemplo de transformación:
|
||||
```python
|
||||
# Código antiguo
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
parser.add_argument(
|
||||
'-g', '--graph-host',
|
||||
default="localhost",
|
||||
help=f'Host del gráfico (predeterminado: localhost)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--graph-username',
|
||||
default=None,
|
||||
help=f'Nombre de usuario de Cassandra'
|
||||
)
|
||||
|
||||
# Código nuevo
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
FlowProcessor.add_args(parser)
|
||||
add_cassandra_args(parser) # Usa el asistente estándar
|
||||
```
|
||||
|
||||
### Actualización de Módulos que Utilizan `cassandra_*` Parámetros
|
||||
1. Agregar soporte para argumentos de línea de comandos (p. ej., `kg-store`)
|
||||
2. Reemplazar las definiciones de argumentos existentes con `add_cassandra_args()`
|
||||
3. Utilizar las funciones `resolve_cassandra_config()` para una resolución consistente
|
||||
4. Asegurar el manejo consistente de las listas de hosts
|
||||
|
||||
### Actualización de Pruebas y Documentación
|
||||
1. Actualizar todos los archivos de prueba
|
||||
2. Actualizar la documentación de la línea de comandos
|
||||
3. Actualizar la documentación de la API
|
||||
4. Actualizar los ejemplos de Docker Compose
|
||||
5. Actualizar la documentación de referencia de la configuración
|
||||
|
||||
## Compatibilidad con versiones anteriores
|
||||
|
||||
Para mantener la compatibilidad con versiones anteriores durante la transición:
|
||||
|
||||
1. **Advertencias de desuso** para los parámetros `graph_*`
|
||||
2. **Alias de parámetros** - aceptar nombres antiguos y nuevos inicialmente
|
||||
3. **Implementación gradual** durante varios lanzamientos
|
||||
4. **Actualizaciones de documentación** con guía de migración
|
||||
|
||||
Ejemplo de código para la compatibilidad con versiones anteriores:
|
||||
```python
|
||||
def __init__(self, **params):
|
||||
# Manejar parámetros graph_* desactualizados
|
||||
if 'graph_host' in params:
|
||||
warnings.warn("graph_host está desactualizado, usa cassandra_host", DeprecationWarning)
|
||||
params.setdefault('cassandra_host', params.pop('graph_host'))
|
||||
|
||||
if 'graph_username' in params:
|
||||
warnings.warn("graph_username está desactualizado, usa cassandra_username", DeprecationWarning)
|
||||
params.setdefault('cassandra_username', params.pop('graph_username'))
|
||||
|
||||
# ... continuar con la resolución estándar
|
||||
```
|
||||
|
||||
## Estrategia de Pruebas
|
||||
|
||||
1. **Pruebas unitarias** para la lógica de resolución de la configuración
|
||||
2. **Pruebas de integración** con diversas combinaciones de configuración
|
||||
3. **Pruebas de variables de entorno**
|
||||
4. **Pruebas de compatibilidad con versiones anteriores** con parámetros desactualizados
|
||||
5. **Pruebas de Docker compose** con variables de entorno
|
||||
|
||||
## Actualizaciones de Documentación
|
||||
|
||||
1. Actualizar toda la documentación de la línea de comandos
|
||||
2. Actualizar la documentación de la API
|
||||
3. Crear una guía de migración
|
||||
4. Actualizar los ejemplos de Docker Compose
|
||||
5. Actualizar la documentación de referencia de la configuración
|
||||
|
||||
## Riesgos y Mitigación
|
||||
|
||||
| Riesgo | Impacto | Mitigación |
|
||||
|------|--------|------------|
|
||||
| Cambios que rompen para los usuarios | Alto | Implementar un período de compatibilidad con versiones anteriores |
|
||||
| Confusión en la configuración durante la transición | Medio | Documentación clara y advertencias de desuso |
|
||||
| Fallos de prueba | Medio | Actualizaciones exhaustivas de prueba |
|
||||
| Problemas de implementación de Docker | Alto | Actualizar todos los ejemplos de Docker Compose |
|
||||
|
||||
## Criterios de Éxito
|
||||
|
||||
- [ ] Todos los módulos utilizan nombres de parámetros consistentes `cassandra_*`
|
||||
- [ ] Todos los procesadores expone la configuración de Cassandra a través de argumentos de línea de comandos
|
||||
- [ ] La salida de la ayuda muestra los valores predeterminados de las variables de entorno
|
||||
- [ ] Los valores de la contraseña nunca se muestran en la ayuda
|
||||
- [ ] La retroalimentación de las variables de entorno funciona correctamente
|
||||
- [ ] El parámetro `cassandra_host` se gestiona de forma consistente como una lista internamente
|
||||
- [ ] Se mantiene la compatibilidad con versiones anteriores durante al menos 2 lanzamientos
|
||||
- [ ] Todas las pruebas pasan con el nuevo sistema de configuración
|
||||
- [ ] La documentación está actualizada
|
||||
- [ ] Los ejemplos de Docker Compose funcionan con las variables de entorno
|
||||
|
||||
## Cronograma
|
||||
|
||||
- **Semana 1:** Implementar el asistente de configuración común y actualizar los módulos que utilizan `graph_*`
|
||||
- **Semana 2:** Agregar soporte de variable de entorno a los módulos existentes que utilizan `cassandra_*`
|
||||
- **Semana 3:** Actualizar las cadenas de documentación
|
||||
- **Semana 4:** Pruebas de integración y correcciones de errores
|
||||
|
||||
## Consideraciones Futuras
|
||||
|
||||
- Considerar extender este patrón a otras configuraciones de bases de datos (p. ej., Elasticsearch)
|
||||
- Implementar la validación de la configuración y mejores mensajes de error
|
||||
- Agregar soporte para la configuración de conexión de piscina (connection pooling)
|
||||
- Considerar agregar soporte para archivos `.env`
|
||||
339
docs/tech-specs/cassandra-consolidation.he.md
Normal file
339
docs/tech-specs/cassandra-consolidation.he.md
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
---
|
||||
layout: default
|
||||
title: "מפרט טכני: איחוד תצורת Cassandra"
|
||||
parent: "Hebrew (Beta)"
|
||||
---
|
||||
|
||||
# מפרט טכני: איחוד תצורת Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**סטטוס:** טיוטה
|
||||
**כותב:** עוזר
|
||||
**תאריך:** 2024-09-03
|
||||
|
||||
## סקירה כללית
|
||||
|
||||
מפרט זה עוסק בדפוסי שמות ותצורות לא עקביים עבור פרמטרי חיבור ל-Cassandra ברחבי בסיס הקוד של TrustGraph. כיום, קיימים שני סכימות שמות פרמטרים שונות (`cassandra_*` לעומת `graph_*`), מה שמוביל לבלבול ולמורכבות תחזוקה.
|
||||
|
||||
## הצגת הבעיה
|
||||
|
||||
בסיס הקוד משתמש כיום בשתי קבוצות נפרדות של פרמטרי תצורה של Cassandra:
|
||||
|
||||
1. **מודולים של Knowledge/Config/Library** משתמשים:
|
||||
`cassandra_host` (רשימת מארחים)
|
||||
`cassandra_user`
|
||||
`cassandra_password`
|
||||
|
||||
2. **מודולים של Graph/Storage** משתמשים:
|
||||
`graph_host` (מאריך יחיד, לעיתים מומר לרשימה)
|
||||
`graph_username`
|
||||
`graph_password`
|
||||
|
||||
3. **חשיפה לא עקבית דרך שורת הפקודה**:
|
||||
חלק מהמעבדים (לדוגמה, `kg-store`) אינם חושפים הגדרות Cassandra כארגומנטים של שורת הפקודה
|
||||
מעבדים אחרים חושפים אותם עם שמות ופורמטים שונים
|
||||
טקסט העזרה אינו משקף ערכי משתני סביבה ברירת מחדל
|
||||
|
||||
שתי קבוצות הפרמטרים מתחברות לאותו кластер Cassandra, אך עם קונבנציות שמות שונות, מה שגורם ל:
|
||||
בלבול בתצורת משתמשים
|
||||
עומס תחזוקה מוגבר
|
||||
תיעוד לא עקבי
|
||||
פוטנציאל לטעות בתצורה
|
||||
חוסר יכולת לשנות הגדרות דרך שורת הפקודה בחלק מהמעבדים
|
||||
|
||||
## פתרון מוצע
|
||||
|
||||
### 1. סטנדרטיזציה של שמות פרמטרים
|
||||
|
||||
כל המודולים ישתמשו בשמות פרמטרים עקביים של `cassandra_*`:
|
||||
`cassandra_host` - רשימת מארחים (מאוחסנת פנימית כרשימה)
|
||||
`cassandra_username` - שם משתמש לאימות
|
||||
`cassandra_password` - סיסמה לאימות
|
||||
|
||||
### 2. ארגומנטים של שורת הפקודה
|
||||
|
||||
כל המעבדים חייבים לחשוף את תצורת Cassandra דרך ארגומנטים של שורת הפקודה:
|
||||
`--cassandra-host` - רשימה מופרדת בפסיקים של מארחים
|
||||
`--cassandra-username` - שם משתמש לאימות
|
||||
`--cassandra-password` - סיסמה לאימות
|
||||
|
||||
### 3. חלופה של משתני סביבה
|
||||
|
||||
אם לא סופקו פרמטרים של שורת הפקודה, המערכת תבדוק משתני סביבה:
|
||||
`CASSANDRA_HOST` - רשימה מופרדת בפסיקים של מארחים
|
||||
`CASSANDRA_USERNAME` - שם משתמש לאימות
|
||||
`CASSANDRA_PASSWORD` - סיסמה לאימות
|
||||
|
||||
### 4. ערכי ברירת מחדל
|
||||
|
||||
אם לא צוינו פרמטרים של שורת פקודה ולא משתני סביבה:
|
||||
`cassandra_host` ברירת המחדל היא `["cassandra"]`
|
||||
`cassandra_username` ברירת המחדל היא `None` (ללא אימות)
|
||||
`cassandra_password` ברירת המחדל היא `None` (ללא אימות)
|
||||
|
||||
### 5. דרישות טקסט עזרה
|
||||
|
||||
הפלט של `--help` חייב:
|
||||
להציג ערכי משתני סביבה כברירות מחדל כאשר הם מוגדרים
|
||||
לעולם לא להציג ערכי סיסמה (להציג `****` או `<set>` במקום)
|
||||
לציין בבירור את סדר הפתרון בטקסט העזרה
|
||||
|
||||
דוגמה לפלט עזרה:
|
||||
```
|
||||
--cassandra-host HOST
|
||||
Cassandra host list, comma-separated (default: prod-cluster-1,prod-cluster-2)
|
||||
[from CASSANDRA_HOST environment variable]
|
||||
|
||||
--cassandra-username USERNAME
|
||||
Cassandra username (default: cassandra_user)
|
||||
[from CASSANDRA_USERNAME environment variable]
|
||||
|
||||
--cassandra-password PASSWORD
|
||||
Cassandra password (default: <set from environment>)
|
||||
```
|
||||
|
||||
## פרטי יישום
|
||||
|
||||
### סדר פתרון פרמטרים
|
||||
|
||||
עבור כל פרמטר של Cassandra, סדר הפתרון יהיה:
|
||||
1. ערך ארגומנט שורת הפקודה
|
||||
2. משתנה סביבה (`CASSANDRA_*`)
|
||||
3. ערך ברירת מחדל
|
||||
|
||||
### טיפול בפרמטרים של מארחים
|
||||
|
||||
הפרמטר `cassandra_host`:
|
||||
שורת הפקודה מקבלת מחרוזת מופרדת בפסיקים: `--cassandra-host "host1,host2,host3"`
|
||||
משתנה סביבה מקבל מחרוזת מופרדת בפסיקים: `CASSANDRA_HOST="host1,host2,host3"`
|
||||
באופן פנימי תמיד מאוחסן כרשימה: `["host1", "host2", "host3"]`
|
||||
מארח בודד: `"localhost"` → מומר ל-`["localhost"]`
|
||||
כבר רשימה: `["host1", "host2"]` → משמש כפי שהוא
|
||||
|
||||
### לוגיקת אימות
|
||||
|
||||
אימות ישמש כאשר גם `cassandra_username` וגם `cassandra_password` מסופקים:
|
||||
```python
|
||||
if cassandra_username and cassandra_password:
|
||||
# Use SSL context and PlainTextAuthProvider
|
||||
else:
|
||||
# Connect without authentication
|
||||
```
|
||||
|
||||
## קבצים שיש לשנות
|
||||
|
||||
### מודולים המשתמשים בפרמטרים `graph_*` (שיש לשנות):
|
||||
`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/rows/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
|
||||
### מודולים המשתמשים בפרמטרים `cassandra_*` (שיש לעדכן עם אפשרות חלופה):
|
||||
`trustgraph-flow/trustgraph/tables/config.py`
|
||||
`trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/tables/library.py`
|
||||
`trustgraph-flow/trustgraph/storage/knowledge/store.py`
|
||||
`trustgraph-flow/trustgraph/cores/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/librarian/librarian.py`
|
||||
`trustgraph-flow/trustgraph/librarian/service.py`
|
||||
`trustgraph-flow/trustgraph/config/service/service.py`
|
||||
`trustgraph-flow/trustgraph/cores/service.py`
|
||||
|
||||
### קבצי בדיקה שיש לעדכן:
|
||||
`tests/unit/test_cores/test_knowledge_manager.py`
|
||||
`tests/unit/test_storage/test_triples_cassandra_storage.py`
|
||||
`tests/unit/test_query/test_triples_cassandra_query.py`
|
||||
`tests/integration/test_objects_cassandra_integration.py`
|
||||
|
||||
## אסטרטגיית יישום
|
||||
|
||||
### שלב 1: יצירת כלי עזר להגדרות משותפות
|
||||
צור פונקציות עזר לסטנדרטיזציה של הגדרות Cassandra בכל המעבדים:
|
||||
|
||||
```python
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def get_cassandra_defaults():
|
||||
"""Get default values from environment variables or fallback."""
|
||||
return {
|
||||
'host': os.getenv('CASSANDRA_HOST', 'cassandra'),
|
||||
'username': os.getenv('CASSANDRA_USERNAME'),
|
||||
'password': os.getenv('CASSANDRA_PASSWORD')
|
||||
}
|
||||
|
||||
def add_cassandra_args(parser: argparse.ArgumentParser):
|
||||
"""
|
||||
Add standardized Cassandra arguments to an argument parser.
|
||||
Shows environment variable values in help text.
|
||||
"""
|
||||
defaults = get_cassandra_defaults()
|
||||
|
||||
# Format help text with env var indication
|
||||
host_help = f"Cassandra host list, comma-separated (default: {defaults['host']})"
|
||||
if 'CASSANDRA_HOST' in os.environ:
|
||||
host_help += " [from CASSANDRA_HOST]"
|
||||
|
||||
username_help = f"Cassandra username"
|
||||
if defaults['username']:
|
||||
username_help += f" (default: {defaults['username']})"
|
||||
if 'CASSANDRA_USERNAME' in os.environ:
|
||||
username_help += " [from CASSANDRA_USERNAME]"
|
||||
|
||||
password_help = "Cassandra password"
|
||||
if defaults['password']:
|
||||
password_help += " (default: <set>)"
|
||||
if 'CASSANDRA_PASSWORD' in os.environ:
|
||||
password_help += " [from CASSANDRA_PASSWORD]"
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-host',
|
||||
default=defaults['host'],
|
||||
help=host_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-username',
|
||||
default=defaults['username'],
|
||||
help=username_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-password',
|
||||
default=defaults['password'],
|
||||
help=password_help
|
||||
)
|
||||
|
||||
def resolve_cassandra_config(args) -> tuple[list[str], str|None, str|None]:
|
||||
"""
|
||||
Convert argparse args to Cassandra configuration.
|
||||
|
||||
Returns:
|
||||
tuple: (hosts_list, username, password)
|
||||
"""
|
||||
# Convert host string to list
|
||||
if isinstance(args.cassandra_host, str):
|
||||
hosts = [h.strip() for h in args.cassandra_host.split(',')]
|
||||
else:
|
||||
hosts = args.cassandra_host
|
||||
|
||||
return hosts, args.cassandra_username, args.cassandra_password
|
||||
```
|
||||
|
||||
### שלב 2: עדכון מודולים באמצעות פרמטרים `graph_*`
|
||||
1. שנה שמות הפרמטרים מ-`graph_*` ל-`cassandra_*`
|
||||
2. החלף שיטות `add_args()` מותאמות אישית בשיטות `add_cassandra_args()` סטנדרטיות
|
||||
3. השתמש בפונקציות העזר לתצורה נפוצות
|
||||
4. עדכן מחרוזות תיעוד
|
||||
|
||||
דוגמה לטרנספורמציה:
|
||||
```python
|
||||
# OLD CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
parser.add_argument(
|
||||
'-g', '--graph-host',
|
||||
default="localhost",
|
||||
help=f'Graph host (default: localhost)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--graph-username',
|
||||
default=None,
|
||||
help=f'Cassandra username'
|
||||
)
|
||||
|
||||
# NEW CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
FlowProcessor.add_args(parser)
|
||||
add_cassandra_args(parser) # Use standard helper
|
||||
```
|
||||
|
||||
### שלב 3: עדכון מודולים באמצעות פרמטרים `cassandra_*`
|
||||
1. הוספת תמיכה בארגומנטים משורת הפקודה היכן שחסרים (לדוגמה, `kg-store`)
|
||||
2. החלפת הגדרות ארגומנטים קיימות ב-`add_cassandra_args()`
|
||||
3. שימוש ב-`resolve_cassandra_config()` עבור פתרון עקבי
|
||||
4. הבטחת טיפול עקבי ברשימת השרתים
|
||||
|
||||
### שלב 4: עדכון בדיקות ותיעוד
|
||||
1. עדכון כל קבצי הבדיקה לשימוש בשמות פרמטרים חדשים
|
||||
2. עדכון תיעוד שורת הפקודה (CLI)
|
||||
3. עדכון תיעוד API
|
||||
4. הוספת תיעוד עבור משתני סביבה
|
||||
|
||||
## תאימות לאחור
|
||||
|
||||
על מנת לשמור על תאימות לאחור במהלך המעבר:
|
||||
|
||||
1. **אזהרות הפסקה** עבור פרמטרים `graph_*`
|
||||
2. **כינוי פרמטרים** - קבלת שמות ישנים וחדשים בתחילה
|
||||
3. **פריסה מדורגת** על פני מספר גרסאות
|
||||
4. **עדכוני תיעוד** עם מדריך מעבר
|
||||
|
||||
דוגמה לקוד תאימות לאחור:
|
||||
```python
|
||||
def __init__(self, **params):
|
||||
# Handle deprecated graph_* parameters
|
||||
if 'graph_host' in params:
|
||||
warnings.warn("graph_host is deprecated, use cassandra_host", DeprecationWarning)
|
||||
params.setdefault('cassandra_host', params.pop('graph_host'))
|
||||
|
||||
if 'graph_username' in params:
|
||||
warnings.warn("graph_username is deprecated, use cassandra_username", DeprecationWarning)
|
||||
params.setdefault('cassandra_username', params.pop('graph_username'))
|
||||
|
||||
# ... continue with standard resolution
|
||||
```
|
||||
|
||||
## אסטרטגיית בדיקות
|
||||
|
||||
1. **בדיקות יחידה** עבור לוגיקת פתרון תצורה
|
||||
2. **בדיקות אינטגרציה** עם שילובים שונים של תצורות
|
||||
3. **בדיקות משתני סביבה**
|
||||
4. **בדיקות תאימות לאחור** עם פרמטרים מיושנים
|
||||
5. **בדיקות Docker Compose** עם משתני סביבה
|
||||
|
||||
## עדכוני תיעוד
|
||||
|
||||
1. עדכון כל התיעוד של פקודות שורת הפקודה
|
||||
2. עדכון תיעוד API
|
||||
3. יצירת מדריך מעבר
|
||||
4. עדכון דוגמאות Docker Compose
|
||||
5. עדכון תיעוד הפניה לתצורה
|
||||
|
||||
## סיכונים ודרכי התמודדות
|
||||
|
||||
| סיכון | השפעה | דרך התמודדות |
|
||||
|------|--------|------------|
|
||||
| שינויים שעלולים לפגוע במשתמשים | גבוהה | יישום תקופת תאימות לאחור |
|
||||
| בלבול בתצורה במהלך המעבר | בינונית | תיעוד ברור ואזהרות על הפסקה |
|
||||
| כשלים בבדיקות | בינונית | עדכוני בדיקות מקיפים |
|
||||
| בעיות בפריסת Docker | גבוהה | עדכון כל דוגמאות Docker Compose |
|
||||
|
||||
## קריטריוני הצלחה
|
||||
|
||||
[ ] כל המודולים משתמשים בשמות פרמטרים אחידים `cassandra_*`
|
||||
[ ] כל המעבדים חושפים הגדרות Cassandra באמצעות ארגומנטים של שורת הפקודה
|
||||
[ ] טקסט העזרה של שורת הפקודה מציג ערכי ברירת מחדל של משתני סביבה
|
||||
[ ] ערכי סיסמה לעולם אינם מוצגים בטקסט העזרה
|
||||
[ ] מנגנון החלפה למשתני סביבה פועל כהלכה
|
||||
[ ] `cassandra_host` מטופל באופן עקבי כרשימה באופן פנימי
|
||||
[ ] תאימות לאחור נשמרת לפחות עבור 2 גרסאות
|
||||
[ ] כל הבדיקות עוברות עם מערכת התצורה החדשה
|
||||
[ ] התיעוד מעודכן במלואו
|
||||
[ ] דוגמאות Docker Compose עובדות עם משתני סביבה
|
||||
|
||||
## ציר זמן
|
||||
|
||||
**שבוע 1:** יישום עזר תצורה משותף ועדכון מודולי `graph_*`
|
||||
**שבוע 2:** הוספת תמיכה במשתני סביבה למודולי `cassandra_*` קיימים
|
||||
**שבוע 3:** עדכון בדיקות ותיעוד
|
||||
**שבוע 4:** בדיקות אינטגרציה ותיקון באגים
|
||||
|
||||
## שיקולים עתידיים
|
||||
|
||||
שקול להרחיב את התבנית הזו לתצורות מסדי נתונים אחרות (לדוגמה, Elasticsearch)
|
||||
יישום אימות תצורה והודעות שגיאה טובות יותר
|
||||
הוספת תמיכה בתצורת חיבור בריכת חיבורים של Cassandra
|
||||
שקול להוסיף תמיכה בקבצי תצורה (.env files)
|
||||
339
docs/tech-specs/cassandra-consolidation.hi.md
Normal file
339
docs/tech-specs/cassandra-consolidation.hi.md
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
---
|
||||
layout: default
|
||||
title: "तकनीकी विनिर्देश: कैसेंड्रा कॉन्फ़िगरेशन समेकन"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# तकनीकी विनिर्देश: कैसेंड्रा कॉन्फ़िगरेशन समेकन
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**स्थिति:** मसौदा
|
||||
**लेखक:** सहायक
|
||||
**तिथि:** 2024-09-03
|
||||
|
||||
## अवलोकन
|
||||
|
||||
यह विनिर्देश ट्रस्टग्राफ कोडबेस में कैसेंड्रा कनेक्शन मापदंडों के लिए असंगत नामकरण और कॉन्फ़िगरेशन पैटर्न को संबोधित करता है। वर्तमान में, दो अलग-अलग पैरामीटर नामकरण योजनाएं मौजूद हैं (`cassandra_*` बनाम `graph_*`), जिससे भ्रम और रखरखाव जटिलता होती है।
|
||||
|
||||
## समस्या विवरण
|
||||
|
||||
कोडबेस वर्तमान में कैसेंड्रा कॉन्फ़िगरेशन मापदंडों के दो अलग-अलग सेट का उपयोग करता है:
|
||||
|
||||
1. **ज्ञान/कॉन्फ़िग/लाइब्रेरी मॉड्यूल** निम्नलिखित का उपयोग करते हैं:
|
||||
`cassandra_host` (होस्ट की सूची)
|
||||
`cassandra_user`
|
||||
`cassandra_password`
|
||||
|
||||
2. **ग्राफ/भंडारण मॉड्यूल** निम्नलिखित का उपयोग करते हैं:
|
||||
`graph_host` (एकल होस्ट, कभी-कभी सूची में परिवर्तित)
|
||||
`graph_username`
|
||||
`graph_password`
|
||||
|
||||
3. **असंगत कमांड-लाइन एक्सपोजर**:
|
||||
कुछ प्रोसेसर (जैसे, `kg-store`) कैसेंड्रा सेटिंग्स को कमांड-लाइन तर्कों के रूप में उजागर नहीं करते हैं
|
||||
अन्य प्रोसेसर उन्हें अलग-अलग नामों और प्रारूपों के साथ उजागर करते हैं
|
||||
सहायता पाठ पर्यावरण चर डिफ़ॉल्ट को प्रतिबिंबित नहीं करता है
|
||||
|
||||
दोनों पैरामीटर सेट एक ही कैसेंड्रा क्लस्टर से जुड़ते हैं, लेकिन अलग-अलग नामकरण सम्मेलनों के साथ, जिससे:
|
||||
उपयोगकर्ताओं के लिए कॉन्फ़िगरेशन भ्रम
|
||||
रखरखाव का बढ़ता बोझ
|
||||
असंगत प्रलेखन
|
||||
गलत कॉन्फ़िगरेशन की संभावना
|
||||
कुछ प्रोसेसर में कमांड-लाइन के माध्यम से सेटिंग्स को ओवरराइड करने में असमर्थता
|
||||
|
||||
## प्रस्तावित समाधान
|
||||
|
||||
### 1. पैरामीटर नामों का मानकीकरण
|
||||
|
||||
सभी मॉड्यूल सुसंगत `cassandra_*` पैरामीटर नामों का उपयोग करेंगे:
|
||||
`cassandra_host` - होस्ट की सूची (आंतरिक रूप से सूची के रूप में संग्रहीत)
|
||||
`cassandra_username` - प्रमाणीकरण के लिए उपयोगकर्ता नाम
|
||||
`cassandra_password` - प्रमाणीकरण के लिए पासवर्ड
|
||||
|
||||
### 2. कमांड-लाइन तर्क
|
||||
|
||||
सभी प्रोसेसर को कैसेंड्रा कॉन्फ़िगरेशन को कमांड-लाइन तर्कों के माध्यम से उजागर करना होगा:
|
||||
`--cassandra-host` - होस्ट की अल्पविराम-विभाजित सूची
|
||||
`--cassandra-username` - प्रमाणीकरण के लिए उपयोगकर्ता नाम
|
||||
`--cassandra-password` - प्रमाणीकरण के लिए पासवर्ड
|
||||
|
||||
### 3. पर्यावरण चर बैकअप
|
||||
|
||||
यदि कमांड-लाइन पैरामीटर स्पष्ट रूप से प्रदान नहीं किए जाते हैं, तो सिस्टम पर्यावरण चर की जांच करेगा:
|
||||
`CASSANDRA_HOST` - होस्ट की अल्पविराम-विभाजित सूची
|
||||
`CASSANDRA_USERNAME` - प्रमाणीकरण के लिए उपयोगकर्ता नाम
|
||||
`CASSANDRA_PASSWORD` - प्रमाणीकरण के लिए पासवर्ड
|
||||
|
||||
### 4. डिफ़ॉल्ट मान
|
||||
|
||||
यदि न तो कमांड-लाइन पैरामीटर और न ही पर्यावरण चर निर्दिष्ट हैं:
|
||||
`cassandra_host` डिफ़ॉल्ट रूप से `["cassandra"]` है
|
||||
`cassandra_username` डिफ़ॉल्ट रूप से `None` है (कोई प्रमाणीकरण नहीं)
|
||||
`cassandra_password` डिफ़ॉल्ट रूप से `None` है (कोई प्रमाणीकरण नहीं)
|
||||
|
||||
### 5. सहायता पाठ आवश्यकताएँ
|
||||
|
||||
`--help` आउटपुट को:
|
||||
जब सेट किया गया हो तो पर्यावरण चर मानों को डिफ़ॉल्ट के रूप में दिखाना चाहिए
|
||||
पासवर्ड मानों को कभी भी प्रदर्शित नहीं करना चाहिए (इसके बजाय `****` या `<set>` दिखाएं)
|
||||
सहायता पाठ में समाधान क्रम को स्पष्ट रूप से इंगित करना चाहिए
|
||||
|
||||
उदाहरण सहायता आउटपुट:
|
||||
```
|
||||
--cassandra-host HOST
|
||||
Cassandra host list, comma-separated (default: prod-cluster-1,prod-cluster-2)
|
||||
[from CASSANDRA_HOST environment variable]
|
||||
|
||||
--cassandra-username USERNAME
|
||||
Cassandra username (default: cassandra_user)
|
||||
[from CASSANDRA_USERNAME environment variable]
|
||||
|
||||
--cassandra-password PASSWORD
|
||||
Cassandra password (default: <set from environment>)
|
||||
```
|
||||
|
||||
## कार्यान्वयन विवरण
|
||||
|
||||
### पैरामीटर समाधान का क्रम
|
||||
|
||||
प्रत्येक कैसेंड्रा पैरामीटर के लिए, समाधान का क्रम इस प्रकार होगा:
|
||||
1. कमांड-लाइन तर्क मान
|
||||
2. पर्यावरण चर (`CASSANDRA_*`)
|
||||
3. डिफ़ॉल्ट मान
|
||||
|
||||
### होस्ट पैरामीटर हैंडलिंग
|
||||
|
||||
`cassandra_host` पैरामीटर:
|
||||
कमांड-लाइन अल्पविराम-विभाजित स्ट्रिंग स्वीकार करता है: `--cassandra-host "host1,host2,host3"`
|
||||
पर्यावरण चर अल्पविराम-विभाजित स्ट्रिंग स्वीकार करता है: `CASSANDRA_HOST="host1,host2,host3"`
|
||||
आंतरिक रूप से हमेशा सूची के रूप में संग्रहीत किया जाता है: `["host1", "host2", "host3"]`
|
||||
एकल होस्ट: `"localhost"` → `["localhost"]` में परिवर्तित
|
||||
पहले से ही एक सूची: `["host1", "host2"]` → जैसा है उपयोग किया जाता है
|
||||
|
||||
### प्रमाणीकरण तर्क
|
||||
|
||||
प्रमाणीकरण का उपयोग तब किया जाएगा जब `cassandra_username` और `cassandra_password` दोनों प्रदान किए जाते हैं:
|
||||
```python
|
||||
if cassandra_username and cassandra_password:
|
||||
# Use SSL context and PlainTextAuthProvider
|
||||
else:
|
||||
# Connect without authentication
|
||||
```
|
||||
|
||||
## संशोधित करने योग्य फ़ाइलें
|
||||
|
||||
### `graph_*` पैरामीटर का उपयोग करने वाले मॉड्यूल (जिन्हें बदला जाना है):
|
||||
`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/rows/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
|
||||
### `cassandra_*` पैरामीटर का उपयोग करने वाले मॉड्यूल (जिन्हें पर्यावरण बैकअप के साथ अपडेट किया जाना है):
|
||||
`trustgraph-flow/trustgraph/tables/config.py`
|
||||
`trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/tables/library.py`
|
||||
`trustgraph-flow/trustgraph/storage/knowledge/store.py`
|
||||
`trustgraph-flow/trustgraph/cores/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/librarian/librarian.py`
|
||||
`trustgraph-flow/trustgraph/librarian/service.py`
|
||||
`trustgraph-flow/trustgraph/config/service/service.py`
|
||||
`trustgraph-flow/trustgraph/cores/service.py`
|
||||
|
||||
### अपडेट करने योग्य परीक्षण फ़ाइलें:
|
||||
`tests/unit/test_cores/test_knowledge_manager.py`
|
||||
`tests/unit/test_storage/test_triples_cassandra_storage.py`
|
||||
`tests/unit/test_query/test_triples_cassandra_query.py`
|
||||
`tests/integration/test_objects_cassandra_integration.py`
|
||||
|
||||
## कार्यान्वयन रणनीति
|
||||
|
||||
### चरण 1: सामान्य कॉन्फ़िगरेशन हेल्पर बनाएं
|
||||
सभी प्रोसेसरों में कैसेंड्रा कॉन्फ़िगरेशन को मानकीकृत करने के लिए उपयोगिता फ़ंक्शन बनाएं:
|
||||
|
||||
```python
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def get_cassandra_defaults():
|
||||
"""Get default values from environment variables or fallback."""
|
||||
return {
|
||||
'host': os.getenv('CASSANDRA_HOST', 'cassandra'),
|
||||
'username': os.getenv('CASSANDRA_USERNAME'),
|
||||
'password': os.getenv('CASSANDRA_PASSWORD')
|
||||
}
|
||||
|
||||
def add_cassandra_args(parser: argparse.ArgumentParser):
|
||||
"""
|
||||
Add standardized Cassandra arguments to an argument parser.
|
||||
Shows environment variable values in help text.
|
||||
"""
|
||||
defaults = get_cassandra_defaults()
|
||||
|
||||
# Format help text with env var indication
|
||||
host_help = f"Cassandra host list, comma-separated (default: {defaults['host']})"
|
||||
if 'CASSANDRA_HOST' in os.environ:
|
||||
host_help += " [from CASSANDRA_HOST]"
|
||||
|
||||
username_help = f"Cassandra username"
|
||||
if defaults['username']:
|
||||
username_help += f" (default: {defaults['username']})"
|
||||
if 'CASSANDRA_USERNAME' in os.environ:
|
||||
username_help += " [from CASSANDRA_USERNAME]"
|
||||
|
||||
password_help = "Cassandra password"
|
||||
if defaults['password']:
|
||||
password_help += " (default: <set>)"
|
||||
if 'CASSANDRA_PASSWORD' in os.environ:
|
||||
password_help += " [from CASSANDRA_PASSWORD]"
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-host',
|
||||
default=defaults['host'],
|
||||
help=host_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-username',
|
||||
default=defaults['username'],
|
||||
help=username_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-password',
|
||||
default=defaults['password'],
|
||||
help=password_help
|
||||
)
|
||||
|
||||
def resolve_cassandra_config(args) -> tuple[list[str], str|None, str|None]:
|
||||
"""
|
||||
Convert argparse args to Cassandra configuration.
|
||||
|
||||
Returns:
|
||||
tuple: (hosts_list, username, password)
|
||||
"""
|
||||
# Convert host string to list
|
||||
if isinstance(args.cassandra_host, str):
|
||||
hosts = [h.strip() for h in args.cassandra_host.split(',')]
|
||||
else:
|
||||
hosts = args.cassandra_host
|
||||
|
||||
return hosts, args.cassandra_username, args.cassandra_password
|
||||
```
|
||||
|
||||
### चरण 2: `graph_*` पैरामीटर का उपयोग करके मॉड्यूल को अपडेट करें
|
||||
1. पैरामीटर नामों को `graph_*` से `cassandra_*` में बदलें
|
||||
2. कस्टम `add_args()` विधियों को मानकीकृत `add_cassandra_args()` से बदलें
|
||||
3. सामान्य कॉन्फ़िगरेशन सहायक फ़ंक्शन का उपयोग करें
|
||||
4. दस्तावेज़ स्ट्रिंग को अपडेट करें
|
||||
|
||||
उदाहरण परिवर्तन:
|
||||
```python
|
||||
# OLD CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
parser.add_argument(
|
||||
'-g', '--graph-host',
|
||||
default="localhost",
|
||||
help=f'Graph host (default: localhost)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--graph-username',
|
||||
default=None,
|
||||
help=f'Cassandra username'
|
||||
)
|
||||
|
||||
# NEW CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
FlowProcessor.add_args(parser)
|
||||
add_cassandra_args(parser) # Use standard helper
|
||||
```
|
||||
|
||||
### चरण 3: `cassandra_*` पैरामीटर का उपयोग करके मॉड्यूल को अपडेट करें
|
||||
1. उन स्थानों पर कमांड-लाइन तर्क समर्थन जोड़ें जहां यह गायब है (उदाहरण के लिए, `kg-store`)
|
||||
2. मौजूदा तर्क परिभाषाओं को `add_cassandra_args()` से बदलें
|
||||
3. सुसंगत समाधान के लिए `resolve_cassandra_config()` का उपयोग करें
|
||||
4. सुसंगत होस्ट सूची प्रबंधन सुनिश्चित करें
|
||||
|
||||
### चरण 4: परीक्षण और दस्तावेज़ को अपडेट करें
|
||||
1. सभी परीक्षण फ़ाइलों को नए पैरामीटर नामों का उपयोग करने के लिए अपडेट करें
|
||||
2. CLI दस्तावेज़ को अपडेट करें
|
||||
3. API दस्तावेज़ को अपडेट करें
|
||||
4. पर्यावरण चर दस्तावेज़ जोड़ें
|
||||
|
||||
## पिछली अनुकूलता
|
||||
|
||||
संक्रमण के दौरान पिछली अनुकूलता बनाए रखने के लिए:
|
||||
|
||||
1. `graph_*` पैरामीटर के लिए **अवरोधन चेतावनी**
|
||||
2. **पैरामीटर उपनाम** - शुरू में पुराने और नए दोनों नामों को स्वीकार करें
|
||||
3. कई रिलीज़ में **चरणबद्ध कार्यान्वयन**
|
||||
4. माइग्रेशन गाइड के साथ **दस्तावेज़ अपडेट**
|
||||
|
||||
पिछली अनुकूलता कोड का उदाहरण:
|
||||
```python
|
||||
def __init__(self, **params):
|
||||
# Handle deprecated graph_* parameters
|
||||
if 'graph_host' in params:
|
||||
warnings.warn("graph_host is deprecated, use cassandra_host", DeprecationWarning)
|
||||
params.setdefault('cassandra_host', params.pop('graph_host'))
|
||||
|
||||
if 'graph_username' in params:
|
||||
warnings.warn("graph_username is deprecated, use cassandra_username", DeprecationWarning)
|
||||
params.setdefault('cassandra_username', params.pop('graph_username'))
|
||||
|
||||
# ... continue with standard resolution
|
||||
```
|
||||
|
||||
## परीक्षण रणनीति
|
||||
|
||||
1. **यूनिट परीक्षण** कॉन्फ़िगरेशन रिज़ॉल्यूशन लॉजिक के लिए
|
||||
2. विभिन्न कॉन्फ़िगरेशन संयोजनों के साथ **एकीकरण परीक्षण**
|
||||
3. **पर्यावरण चर परीक्षण**
|
||||
4. **पिछड़ा संगतता परीक्षण** अप्रचलित मापदंडों के साथ
|
||||
5. **डॉकर कंपोज़ परीक्षण** पर्यावरण चर के साथ
|
||||
|
||||
## दस्तावेज़ अपडेट
|
||||
|
||||
1. सभी CLI कमांड दस्तावेज़ों को अपडेट करें
|
||||
2. API दस्तावेज़ों को अपडेट करें
|
||||
3. माइग्रेशन गाइड बनाएं
|
||||
4. डॉकर कंपोज़ उदाहरणों को अपडेट करें
|
||||
5. कॉन्फ़िगरेशन संदर्भ दस्तावेज़ को अपडेट करें
|
||||
|
||||
## जोखिम और निवारण
|
||||
|
||||
| जोखिम | प्रभाव | निवारण |
|
||||
|------|--------|------------|
|
||||
| उपयोगकर्ताओं के लिए ब्रेकिंग परिवर्तन | उच्च | पिछड़े संगतता अवधि लागू करें |
|
||||
| संक्रमण के दौरान कॉन्फ़िगरेशन भ्रम | मध्यम | स्पष्ट दस्तावेज़ और अवमूल्यन चेतावनियाँ |
|
||||
| परीक्षण विफलताएँ | मध्यम | व्यापक परीक्षण अपडेट |
|
||||
| डॉकर परिनियोजन मुद्दे | उच्च | सभी डॉकर कंपोज़ उदाहरणों को अपडेट करें |
|
||||
|
||||
## सफलता मानदंड
|
||||
|
||||
[ ] सभी मॉड्यूल सुसंगत `cassandra_*` पैरामीटर नामों का उपयोग करते हैं
|
||||
[ ] सभी प्रोसेसर कमांड-लाइन तर्कों के माध्यम से कैसेंड्रा सेटिंग्स को उजागर करते हैं
|
||||
[ ] कमांड-लाइन सहायता पाठ पर्यावरण चर डिफ़ॉल्ट दिखाता है
|
||||
[ ] पासवर्ड मान कभी भी सहायता पाठ में प्रदर्शित नहीं होते हैं
|
||||
[ ] पर्यावरण चर बैकअप सही ढंग से काम करता है
|
||||
[ ] `cassandra_host` को आंतरिक रूप से लगातार एक सूची के रूप में संभाला जाता है
|
||||
[ ] कम से कम 2 रिलीज़ के लिए पिछड़े संगतता बनाए रखी जाती है
|
||||
[ ] सभी परीक्षण नए कॉन्फ़िगरेशन सिस्टम के साथ पास होते हैं
|
||||
[ ] दस्तावेज़ पूरी तरह से अपडेट किया गया है
|
||||
[ ] डॉकर कंपोज़ उदाहरण पर्यावरण चर के साथ काम करते हैं
|
||||
|
||||
## समयरेखा
|
||||
|
||||
**सप्ताह 1:** सामान्य कॉन्फ़िगरेशन हेल्पर लागू करें और `graph_*` मॉड्यूल को अपडेट करें
|
||||
**सप्ताह 2:** मौजूदा `cassandra_*` मॉड्यूल में पर्यावरण चर समर्थन जोड़ें
|
||||
**सप्ताह 3:** परीक्षण और दस्तावेज़ अपडेट करें
|
||||
**सप्ताह 4:** एकीकरण परीक्षण और बग फिक्स
|
||||
|
||||
## भविष्य के विचार
|
||||
|
||||
अन्य डेटाबेस कॉन्फ़िगरेशन (जैसे, Elasticsearch) के लिए इस पैटर्न को विस्तारित करने पर विचार करें
|
||||
कॉन्फ़िगरेशन सत्यापन और बेहतर त्रुटि संदेश लागू करें
|
||||
कैसेंड्रा कनेक्शन पूलिंग कॉन्फ़िगरेशन के लिए समर्थन जोड़ें
|
||||
कॉन्फ़िगरेशन फ़ाइल समर्थन (.env फ़ाइलें) जोड़ने पर विचार करें
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Tech Spec: Cassandra Configuration Consolidation"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Tech Spec: Cassandra Configuration Consolidation
|
||||
|
||||
**Status:** Draft
|
||||
|
|
@ -328,4 +334,4 @@ def __init__(self, **params):
|
|||
- Consider extending this pattern to other database configurations (e.g., Elasticsearch)
|
||||
- Implement configuration validation and better error messages
|
||||
- Add support for Cassandra connection pooling configuration
|
||||
- Consider adding configuration file support (.env files)
|
||||
- Consider adding configuration file support (.env files)
|
||||
|
|
|
|||
339
docs/tech-specs/cassandra-consolidation.pt.md
Normal file
339
docs/tech-specs/cassandra-consolidation.pt.md
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificação Técnica: Consolidação da Configuração do Cassandra"
|
||||
parent: "Portuguese (Beta)"
|
||||
---
|
||||
|
||||
# Especificação Técnica: Consolidação da Configuração do Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**Status:** Rascunho
|
||||
**Autor:** Assistente
|
||||
**Data:** 2024-09-03
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Esta especificação aborda os padrões de nomenclatura e configuração inconsistentes para os parâmetros de conexão do Cassandra em todo o código-fonte do TrustGraph. Atualmente, existem dois esquemas de nomenclatura de parâmetros diferentes (`cassandra_*` vs `graph_*`), o que leva à confusão e à complexidade da manutenção.
|
||||
|
||||
## Declaração do Problema
|
||||
|
||||
O código-fonte atualmente usa dois conjuntos distintos de parâmetros de configuração do Cassandra:
|
||||
|
||||
1. **Módulos Knowledge/Config/Library** usam:
|
||||
`cassandra_host` (lista de hosts)
|
||||
`cassandra_user`
|
||||
`cassandra_password`
|
||||
|
||||
2. **Módulos Graph/Storage** usam:
|
||||
`graph_host` (um único host, às vezes convertido em lista)
|
||||
`graph_username`
|
||||
`graph_password`
|
||||
|
||||
3. **Exposição inconsistente na linha de comando**:
|
||||
Alguns processadores (por exemplo, `kg-store`) não expõem as configurações do Cassandra como argumentos de linha de comando
|
||||
Outros processadores os expõem com nomes e formatos diferentes
|
||||
O texto de ajuda não reflete os valores padrão das variáveis de ambiente
|
||||
|
||||
Ambos os conjuntos de parâmetros se conectam ao mesmo cluster Cassandra, mas com convenções de nomenclatura diferentes, causando:
|
||||
Confusão na configuração para os usuários
|
||||
Aumento da carga de manutenção
|
||||
Documentação inconsistente
|
||||
Potencial para configuração incorreta
|
||||
Impossibilidade de substituir as configurações via linha de comando em alguns processadores
|
||||
|
||||
## Solução Proposta
|
||||
|
||||
### 1. Padronização dos Nomes dos Parâmetros
|
||||
|
||||
Todos os módulos usarão nomes de parâmetros `cassandra_*` consistentes:
|
||||
`cassandra_host` - Lista de hosts (armazenada internamente como lista)
|
||||
`cassandra_username` - Nome de usuário para autenticação
|
||||
`cassandra_password` - Senha para autenticação
|
||||
|
||||
### 2. Argumentos da Linha de Comando
|
||||
|
||||
Todos os processadores DEVEM expor a configuração do Cassandra por meio de argumentos de linha de comando:
|
||||
`--cassandra-host` - Lista separada por vírgulas de hosts
|
||||
`--cassandra-username` - Nome de usuário para autenticação
|
||||
`--cassandra-password` - Senha para autenticação
|
||||
|
||||
### 3. Fallback de Variáveis de Ambiente
|
||||
|
||||
Se os parâmetros da linha de comando não forem fornecidos explicitamente, o sistema verificará as variáveis de ambiente:
|
||||
`CASSANDRA_HOST` - Lista separada por vírgulas de hosts
|
||||
`CASSANDRA_USERNAME` - Nome de usuário para autenticação
|
||||
`CASSANDRA_PASSWORD` - Senha para autenticação
|
||||
|
||||
### 4. Valores Padrão
|
||||
|
||||
Se nem os parâmetros da linha de comando nem as variáveis de ambiente forem especificados:
|
||||
`cassandra_host` tem como padrão `["cassandra"]`
|
||||
`cassandra_username` tem como padrão `None` (sem autenticação)
|
||||
`cassandra_password` tem como padrão `None` (sem autenticação)
|
||||
|
||||
### 5. Requisitos do Texto de Ajuda
|
||||
|
||||
A saída `--help` deve:
|
||||
Mostrar os valores das variáveis de ambiente como padrões quando definidos
|
||||
Nunca exibir valores de senha (exibir `****` ou `<set>` em vez disso)
|
||||
Indicar claramente a ordem de resolução no texto de ajuda
|
||||
|
||||
Exemplo de saída de ajuda:
|
||||
```
|
||||
--cassandra-host HOST
|
||||
Cassandra host list, comma-separated (default: prod-cluster-1,prod-cluster-2)
|
||||
[from CASSANDRA_HOST environment variable]
|
||||
|
||||
--cassandra-username USERNAME
|
||||
Cassandra username (default: cassandra_user)
|
||||
[from CASSANDRA_USERNAME environment variable]
|
||||
|
||||
--cassandra-password PASSWORD
|
||||
Cassandra password (default: <set from environment>)
|
||||
```
|
||||
|
||||
## Detalhes de Implementação
|
||||
|
||||
### Ordem de Resolução de Parâmetros
|
||||
|
||||
Para cada parâmetro do Cassandra, a ordem de resolução será:
|
||||
1. Valor do argumento de linha de comando
|
||||
2. Variável de ambiente (`CASSANDRA_*`)
|
||||
3. Valor padrão
|
||||
|
||||
### Tratamento de Parâmetros de Host
|
||||
|
||||
O parâmetro `cassandra_host`:
|
||||
A linha de comando aceita uma string separada por vírgulas: `--cassandra-host "host1,host2,host3"`
|
||||
A variável de ambiente aceita uma string separada por vírgulas: `CASSANDRA_HOST="host1,host2,host3"`
|
||||
Internamente sempre armazenado como uma lista: `["host1", "host2", "host3"]`
|
||||
Host único: `"localhost"` → convertido para `["localhost"]`
|
||||
Já é uma lista: `["host1", "host2"]` → usado como está
|
||||
|
||||
### Lógica de Autenticação
|
||||
|
||||
A autenticação será usada quando tanto `cassandra_username` quanto `cassandra_password` forem fornecidos:
|
||||
```python
|
||||
if cassandra_username and cassandra_password:
|
||||
# Use SSL context and PlainTextAuthProvider
|
||||
else:
|
||||
# Connect without authentication
|
||||
```
|
||||
|
||||
## Arquivos a serem modificados
|
||||
|
||||
### Módulos que utilizam parâmetros `graph_*` (a serem alterados):
|
||||
`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/rows/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
|
||||
### Módulos que utilizam parâmetros `cassandra_*` (a serem atualizados com fallback do ambiente):
|
||||
`trustgraph-flow/trustgraph/tables/config.py`
|
||||
`trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/tables/library.py`
|
||||
`trustgraph-flow/trustgraph/storage/knowledge/store.py`
|
||||
`trustgraph-flow/trustgraph/cores/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/librarian/librarian.py`
|
||||
`trustgraph-flow/trustgraph/librarian/service.py`
|
||||
`trustgraph-flow/trustgraph/config/service/service.py`
|
||||
`trustgraph-flow/trustgraph/cores/service.py`
|
||||
|
||||
### Arquivos de teste a serem atualizados:
|
||||
`tests/unit/test_cores/test_knowledge_manager.py`
|
||||
`tests/unit/test_storage/test_triples_cassandra_storage.py`
|
||||
`tests/unit/test_query/test_triples_cassandra_query.py`
|
||||
`tests/integration/test_objects_cassandra_integration.py`
|
||||
|
||||
## Estratégia de implementação
|
||||
|
||||
### Fase 1: Criar um utilitário de configuração comum
|
||||
Crie funções utilitárias para padronizar a configuração do Cassandra em todos os processadores:
|
||||
|
||||
```python
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def get_cassandra_defaults():
|
||||
"""Get default values from environment variables or fallback."""
|
||||
return {
|
||||
'host': os.getenv('CASSANDRA_HOST', 'cassandra'),
|
||||
'username': os.getenv('CASSANDRA_USERNAME'),
|
||||
'password': os.getenv('CASSANDRA_PASSWORD')
|
||||
}
|
||||
|
||||
def add_cassandra_args(parser: argparse.ArgumentParser):
|
||||
"""
|
||||
Add standardized Cassandra arguments to an argument parser.
|
||||
Shows environment variable values in help text.
|
||||
"""
|
||||
defaults = get_cassandra_defaults()
|
||||
|
||||
# Format help text with env var indication
|
||||
host_help = f"Cassandra host list, comma-separated (default: {defaults['host']})"
|
||||
if 'CASSANDRA_HOST' in os.environ:
|
||||
host_help += " [from CASSANDRA_HOST]"
|
||||
|
||||
username_help = f"Cassandra username"
|
||||
if defaults['username']:
|
||||
username_help += f" (default: {defaults['username']})"
|
||||
if 'CASSANDRA_USERNAME' in os.environ:
|
||||
username_help += " [from CASSANDRA_USERNAME]"
|
||||
|
||||
password_help = "Cassandra password"
|
||||
if defaults['password']:
|
||||
password_help += " (default: <set>)"
|
||||
if 'CASSANDRA_PASSWORD' in os.environ:
|
||||
password_help += " [from CASSANDRA_PASSWORD]"
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-host',
|
||||
default=defaults['host'],
|
||||
help=host_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-username',
|
||||
default=defaults['username'],
|
||||
help=username_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-password',
|
||||
default=defaults['password'],
|
||||
help=password_help
|
||||
)
|
||||
|
||||
def resolve_cassandra_config(args) -> tuple[list[str], str|None, str|None]:
|
||||
"""
|
||||
Convert argparse args to Cassandra configuration.
|
||||
|
||||
Returns:
|
||||
tuple: (hosts_list, username, password)
|
||||
"""
|
||||
# Convert host string to list
|
||||
if isinstance(args.cassandra_host, str):
|
||||
hosts = [h.strip() for h in args.cassandra_host.split(',')]
|
||||
else:
|
||||
hosts = args.cassandra_host
|
||||
|
||||
return hosts, args.cassandra_username, args.cassandra_password
|
||||
```
|
||||
|
||||
### Fase 2: Atualizar Módulos Usando Parâmetros `graph_*`
|
||||
1. Alterar os nomes dos parâmetros de `graph_*` para `cassandra_*`
|
||||
2. Substituir os métodos personalizados `add_args()` por métodos padronizados `add_cassandra_args()`
|
||||
3. Usar as funções auxiliares de configuração comuns
|
||||
4. Atualizar as strings de documentação
|
||||
|
||||
Exemplo de transformação:
|
||||
```python
|
||||
# OLD CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
parser.add_argument(
|
||||
'-g', '--graph-host',
|
||||
default="localhost",
|
||||
help=f'Graph host (default: localhost)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--graph-username',
|
||||
default=None,
|
||||
help=f'Cassandra username'
|
||||
)
|
||||
|
||||
# NEW CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
FlowProcessor.add_args(parser)
|
||||
add_cassandra_args(parser) # Use standard helper
|
||||
```
|
||||
|
||||
### Fase 3: Atualizar Módulos Usando Parâmetros `cassandra_*`
|
||||
1. Adicionar suporte para argumentos de linha de comando onde estiver faltando (por exemplo, `kg-store`)
|
||||
2. Substituir as definições de argumentos existentes por `add_cassandra_args()`
|
||||
3. Usar `resolve_cassandra_config()` para resolução consistente
|
||||
4. Garantir o tratamento consistente da lista de hosts
|
||||
|
||||
### Fase 4: Atualizar Testes e Documentação
|
||||
1. Atualizar todos os arquivos de teste para usar os novos nomes de parâmetros
|
||||
2. Atualizar a documentação da CLI
|
||||
3. Atualizar a documentação da API
|
||||
4. Adicionar documentação de variáveis de ambiente
|
||||
|
||||
## Compatibilidade com Versões Anteriores
|
||||
|
||||
Para manter a compatibilidade com versões anteriores durante a transição:
|
||||
|
||||
1. **Avisos de descontinuação** para parâmetros `graph_*`
|
||||
2. **Aliasing de parâmetros** - aceitar tanto os nomes antigos quanto os novos inicialmente
|
||||
3. **Implementação gradual** ao longo de várias versões
|
||||
4. **Atualizações na documentação** com um guia de migração
|
||||
|
||||
Exemplo de código de compatibilidade com versões anteriores:
|
||||
```python
|
||||
def __init__(self, **params):
|
||||
# Handle deprecated graph_* parameters
|
||||
if 'graph_host' in params:
|
||||
warnings.warn("graph_host is deprecated, use cassandra_host", DeprecationWarning)
|
||||
params.setdefault('cassandra_host', params.pop('graph_host'))
|
||||
|
||||
if 'graph_username' in params:
|
||||
warnings.warn("graph_username is deprecated, use cassandra_username", DeprecationWarning)
|
||||
params.setdefault('cassandra_username', params.pop('graph_username'))
|
||||
|
||||
# ... continue with standard resolution
|
||||
```
|
||||
|
||||
## Estratégia de Testes
|
||||
|
||||
1. **Testes unitários** para a lógica de resolução de configuração
|
||||
2. **Testes de integração** com várias combinações de configuração
|
||||
3. **Testes de variáveis de ambiente**
|
||||
4. **Testes de compatibilidade retroativa** com parâmetros obsoletos
|
||||
5. **Testes do Docker Compose** com variáveis de ambiente
|
||||
|
||||
## Atualizações da Documentação
|
||||
|
||||
1. Atualizar toda a documentação dos comandos da linha de comando
|
||||
2. Atualizar a documentação da API
|
||||
3. Criar um guia de migração
|
||||
4. Atualizar os exemplos do Docker Compose
|
||||
5. Atualizar a documentação de referência de configuração
|
||||
|
||||
## Riscos e Mitigações
|
||||
|
||||
| Risco | Impacto | Mitigação |
|
||||
|------|--------|------------|
|
||||
| Mudanças que podem afetar os usuários | Alto | Implementar um período de compatibilidade retroativa |
|
||||
| Confusão na configuração durante a transição | Médio | Documentação clara e avisos de descontinuação |
|
||||
| Falhas nos testes | Médio | Atualizações abrangentes nos testes |
|
||||
| Problemas de implantação do Docker | Alto | Atualizar todos os exemplos do Docker Compose |
|
||||
|
||||
## Critérios de Sucesso
|
||||
|
||||
[ ] Todos os módulos usam nomes de parâmetros `cassandra_*` consistentes
|
||||
[ ] Todos os processadores expõem as configurações do Cassandra por meio de argumentos da linha de comando
|
||||
[ ] O texto de ajuda da linha de comando mostra os valores padrão das variáveis de ambiente
|
||||
[ ] Os valores de senha nunca são exibidos no texto de ajuda
|
||||
[ ] O fallback de variáveis de ambiente funciona corretamente
|
||||
[ ] `cassandra_host` é tratado de forma consistente como uma lista internamente
|
||||
[ ] A compatibilidade retroativa é mantida por pelo menos 2 versões
|
||||
[ ] Todos os testes passam com o novo sistema de configuração
|
||||
[ ] A documentação está totalmente atualizada
|
||||
[ ] Os exemplos do Docker Compose funcionam com variáveis de ambiente
|
||||
|
||||
## Cronograma
|
||||
|
||||
**Semana 1:** Implementar o utilitário de configuração comum e atualizar os módulos `graph_*`
|
||||
**Semana 2:** Adicionar suporte a variáveis de ambiente aos módulos `cassandra_*` existentes
|
||||
**Semana 3:** Atualizar testes e documentação
|
||||
**Semana 4:** Testes de integração e correção de bugs
|
||||
|
||||
## Considerações Futuras
|
||||
|
||||
Considerar a extensão desse padrão para outras configurações de banco de dados (por exemplo, Elasticsearch)
|
||||
Implementar validação de configuração e melhores mensagens de erro
|
||||
Adicionar suporte para configuração de pool de conexões do Cassandra
|
||||
Considerar a adição de suporte para arquivos de configuração (.env)
|
||||
339
docs/tech-specs/cassandra-consolidation.ru.md
Normal file
339
docs/tech-specs/cassandra-consolidation.ru.md
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Техническое описание: Консолидация конфигурации Cassandra"
|
||||
parent: "Russian (Beta)"
|
||||
---
|
||||
|
||||
# Техническое описание: Консолидация конфигурации Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**Статус:** Черновик
|
||||
**Автор:** Assistant
|
||||
**Дата:** 2024-09-03
|
||||
|
||||
## Обзор
|
||||
|
||||
Данное техническое описание посвящено неконсистентности именования и шаблонов конфигурации параметров подключения к Cassandra в кодовой базе TrustGraph. В настоящее время существуют две различные схемы именования параметров (`cassandra_*` против `graph_*`), что приводит к путанице и усложняет обслуживание.
|
||||
|
||||
## Описание проблемы
|
||||
|
||||
В кодовой базе в настоящее время используются два различных набора параметров конфигурации Cassandra:
|
||||
|
||||
1. **Модули Knowledge/Config/Library** используют:
|
||||
`cassandra_host` (список хостов)
|
||||
`cassandra_user`
|
||||
`cassandra_password`
|
||||
|
||||
2. **Модули Graph/Storage** используют:
|
||||
`graph_host` (один хост, иногда преобразуется в список)
|
||||
`graph_username`
|
||||
`graph_password`
|
||||
|
||||
3. **Неконсистентное использование в командной строке**:
|
||||
Некоторые процессоры (например, `kg-store`) не предоставляют параметры Cassandra в качестве аргументов командной строки
|
||||
Другие процессоры предоставляют их с разными именами и форматами
|
||||
Тексты справки не отражают значения переменных окружения по умолчанию
|
||||
|
||||
Оба набора параметров подключаются к одному кластеру Cassandra, но с разными соглашениями об именовании, что приводит к:
|
||||
Путанице в конфигурации для пользователей
|
||||
Увеличенной нагрузке на обслуживание
|
||||
Неконсистентной документации
|
||||
Возможности неправильной конфигурации
|
||||
Невозможности перезаписать настройки через командную строку в некоторых процессорах
|
||||
|
||||
## Предлагаемое решение
|
||||
|
||||
### 1. Стандартизация имен параметров
|
||||
|
||||
Все модули будут использовать согласованные имена параметров `cassandra_*`:
|
||||
`cassandra_host` - Список хостов (хранится внутри как список)
|
||||
`cassandra_username` - Имя пользователя для аутентификации
|
||||
`cassandra_password` - Пароль для аутентификации
|
||||
|
||||
### 2. Аргументы командной строки
|
||||
|
||||
Все процессоры ДОЛЖНЫ предоставлять конфигурацию Cassandra через аргументы командной строки:
|
||||
`--cassandra-host` - Список хостов, разделенный запятыми
|
||||
`--cassandra-username` - Имя пользователя для аутентификации
|
||||
`--cassandra-password` - Пароль для аутентификации
|
||||
|
||||
### 3. Передача через переменные окружения
|
||||
|
||||
Если параметры командной строки не указаны явно, система будет проверять переменные окружения:
|
||||
`CASSANDRA_HOST` - Список хостов, разделенный запятыми
|
||||
`CASSANDRA_USERNAME` - Имя пользователя для аутентификации
|
||||
`CASSANDRA_PASSWORD` - Пароль для аутентификации
|
||||
|
||||
### 4. Значения по умолчанию
|
||||
|
||||
Если ни параметры командной строки, ни переменные окружения не указаны:
|
||||
`cassandra_host` по умолчанию `["cassandra"]`
|
||||
`cassandra_username` по умолчанию `None` (без аутентификации)
|
||||
`cassandra_password` по умолчанию `None` (без аутентификации)
|
||||
|
||||
### 5. Требования к тексту справки
|
||||
|
||||
Вывод команды `--help` должен:
|
||||
Показывать значения переменных окружения в качестве значений по умолчанию, если они установлены
|
||||
Никогда не отображать значения паролей (показывать `****` или `<set>` вместо этого)
|
||||
Четко указывать порядок разрешения в тексте справки
|
||||
|
||||
Пример вывода справки:
|
||||
```
|
||||
--cassandra-host HOST
|
||||
Cassandra host list, comma-separated (default: prod-cluster-1,prod-cluster-2)
|
||||
[from CASSANDRA_HOST environment variable]
|
||||
|
||||
--cassandra-username USERNAME
|
||||
Cassandra username (default: cassandra_user)
|
||||
[from CASSANDRA_USERNAME environment variable]
|
||||
|
||||
--cassandra-password PASSWORD
|
||||
Cassandra password (default: <set from environment>)
|
||||
```
|
||||
|
||||
## Детали реализации
|
||||
|
||||
### Порядок разрешения параметров
|
||||
|
||||
Для каждого параметра Cassandra порядок разрешения будет следующим:
|
||||
1. Значение аргумента командной строки
|
||||
2. Значение переменной окружения (`CASSANDRA_*`)
|
||||
3. Значение по умолчанию
|
||||
|
||||
### Обработка параметров хостов
|
||||
|
||||
Параметр `cassandra_host`:
|
||||
Командная строка принимает строку, разделенную запятыми: `--cassandra-host "host1,host2,host3"`
|
||||
Переменная окружения принимает строку, разделенную запятыми: `CASSANDRA_HOST="host1,host2,host3"`
|
||||
Внутри всегда хранится в виде списка: `["host1", "host2", "host3"]`
|
||||
Один хост: `"localhost"` → преобразуется в `["localhost"]`
|
||||
Уже является списком: `["host1", "host2"]` → используется как есть
|
||||
|
||||
### Логика аутентификации
|
||||
|
||||
Аутентификация будет использоваться, когда указаны и `cassandra_username`, и `cassandra_password`:
|
||||
```python
|
||||
if cassandra_username and cassandra_password:
|
||||
# Use SSL context and PlainTextAuthProvider
|
||||
else:
|
||||
# Connect without authentication
|
||||
```
|
||||
|
||||
## Файлы для изменения
|
||||
|
||||
### Модули, использующие параметры `graph_*` (которые необходимо изменить):
|
||||
`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/rows/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
|
||||
### Модули, использующие параметры `cassandra_*` (которые необходимо обновить с использованием резервного варианта из среды):
|
||||
`trustgraph-flow/trustgraph/tables/config.py`
|
||||
`trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/tables/library.py`
|
||||
`trustgraph-flow/trustgraph/storage/knowledge/store.py`
|
||||
`trustgraph-flow/trustgraph/cores/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/librarian/librarian.py`
|
||||
`trustgraph-flow/trustgraph/librarian/service.py`
|
||||
`trustgraph-flow/trustgraph/config/service/service.py`
|
||||
`trustgraph-flow/trustgraph/cores/service.py`
|
||||
|
||||
### Тестовые файлы для обновления:
|
||||
`tests/unit/test_cores/test_knowledge_manager.py`
|
||||
`tests/unit/test_storage/test_triples_cassandra_storage.py`
|
||||
`tests/unit/test_query/test_triples_cassandra_query.py`
|
||||
`tests/integration/test_objects_cassandra_integration.py`
|
||||
|
||||
## Стратегия реализации
|
||||
|
||||
### Этап 1: Создание общего вспомогательного класса конфигурации
|
||||
Создайте вспомогательные функции для стандартизации конфигурации Cassandra во всех процессорах:
|
||||
|
||||
```python
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def get_cassandra_defaults():
|
||||
"""Get default values from environment variables or fallback."""
|
||||
return {
|
||||
'host': os.getenv('CASSANDRA_HOST', 'cassandra'),
|
||||
'username': os.getenv('CASSANDRA_USERNAME'),
|
||||
'password': os.getenv('CASSANDRA_PASSWORD')
|
||||
}
|
||||
|
||||
def add_cassandra_args(parser: argparse.ArgumentParser):
|
||||
"""
|
||||
Add standardized Cassandra arguments to an argument parser.
|
||||
Shows environment variable values in help text.
|
||||
"""
|
||||
defaults = get_cassandra_defaults()
|
||||
|
||||
# Format help text with env var indication
|
||||
host_help = f"Cassandra host list, comma-separated (default: {defaults['host']})"
|
||||
if 'CASSANDRA_HOST' in os.environ:
|
||||
host_help += " [from CASSANDRA_HOST]"
|
||||
|
||||
username_help = f"Cassandra username"
|
||||
if defaults['username']:
|
||||
username_help += f" (default: {defaults['username']})"
|
||||
if 'CASSANDRA_USERNAME' in os.environ:
|
||||
username_help += " [from CASSANDRA_USERNAME]"
|
||||
|
||||
password_help = "Cassandra password"
|
||||
if defaults['password']:
|
||||
password_help += " (default: <set>)"
|
||||
if 'CASSANDRA_PASSWORD' in os.environ:
|
||||
password_help += " [from CASSANDRA_PASSWORD]"
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-host',
|
||||
default=defaults['host'],
|
||||
help=host_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-username',
|
||||
default=defaults['username'],
|
||||
help=username_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-password',
|
||||
default=defaults['password'],
|
||||
help=password_help
|
||||
)
|
||||
|
||||
def resolve_cassandra_config(args) -> tuple[list[str], str|None, str|None]:
|
||||
"""
|
||||
Convert argparse args to Cassandra configuration.
|
||||
|
||||
Returns:
|
||||
tuple: (hosts_list, username, password)
|
||||
"""
|
||||
# Convert host string to list
|
||||
if isinstance(args.cassandra_host, str):
|
||||
hosts = [h.strip() for h in args.cassandra_host.split(',')]
|
||||
else:
|
||||
hosts = args.cassandra_host
|
||||
|
||||
return hosts, args.cassandra_username, args.cassandra_password
|
||||
```
|
||||
|
||||
### Фаза 2: Обновление модулей с использованием параметров `graph_*`
|
||||
1. Изменить имена параметров с `graph_*` на `cassandra_*`
|
||||
2. Заменить собственные методы `add_args()` на стандартизированные методы `add_cassandra_args()`
|
||||
3. Использовать общие вспомогательные функции конфигурации
|
||||
4. Обновить строки документации
|
||||
|
||||
Пример преобразования:
|
||||
```python
|
||||
# OLD CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
parser.add_argument(
|
||||
'-g', '--graph-host',
|
||||
default="localhost",
|
||||
help=f'Graph host (default: localhost)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--graph-username',
|
||||
default=None,
|
||||
help=f'Cassandra username'
|
||||
)
|
||||
|
||||
# NEW CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
FlowProcessor.add_args(parser)
|
||||
add_cassandra_args(parser) # Use standard helper
|
||||
```
|
||||
|
||||
### Фаза 3: Обновление модулей с использованием параметров `cassandra_*`
|
||||
1. Добавить поддержку аргументов командной строки там, где это отсутствует (например, `kg-store`).
|
||||
2. Заменить существующие определения аргументов на `add_cassandra_args()`.
|
||||
3. Использовать `resolve_cassandra_config()` для обеспечения согласованности разрешения.
|
||||
4. Обеспечить согласованную обработку списка хостов.
|
||||
|
||||
### Фаза 4: Обновление тестов и документации
|
||||
1. Обновить все файлы тестов для использования новых имен параметров.
|
||||
2. Обновить документацию CLI.
|
||||
3. Обновить документацию API.
|
||||
4. Добавить документацию по переменным окружения.
|
||||
|
||||
## Обратная совместимость
|
||||
|
||||
Для поддержания обратной совместимости во время перехода:
|
||||
|
||||
1. **Предупреждения об устаревании** для параметров `graph_*`.
|
||||
2. **Псевдонимы параметров** - изначально принимать как старые, так и новые имена.
|
||||
3. **Поэтапное внедрение** в течение нескольких релизов.
|
||||
4. **Обновления документации** с руководством по миграции.
|
||||
|
||||
Пример кода обратной совместимости:
|
||||
```python
|
||||
def __init__(self, **params):
|
||||
# Handle deprecated graph_* parameters
|
||||
if 'graph_host' in params:
|
||||
warnings.warn("graph_host is deprecated, use cassandra_host", DeprecationWarning)
|
||||
params.setdefault('cassandra_host', params.pop('graph_host'))
|
||||
|
||||
if 'graph_username' in params:
|
||||
warnings.warn("graph_username is deprecated, use cassandra_username", DeprecationWarning)
|
||||
params.setdefault('cassandra_username', params.pop('graph_username'))
|
||||
|
||||
# ... continue with standard resolution
|
||||
```
|
||||
|
||||
## Стратегия тестирования
|
||||
|
||||
1. **Юнит-тесты** для логики разрешения конфигурации
|
||||
2. **Интеграционные тесты** с различными комбинациями конфигурации
|
||||
3. **Тесты переменных окружения**
|
||||
4. **Тесты обратной совместимости** с устаревшими параметрами
|
||||
5. **Тесты Docker Compose** с переменными окружения
|
||||
|
||||
## Обновления документации
|
||||
|
||||
1. Обновить всю документацию по командам CLI
|
||||
2. Обновить документацию API
|
||||
3. Создать руководство по миграции
|
||||
4. Обновить примеры Docker Compose
|
||||
5. Обновить справочную документацию по конфигурации
|
||||
|
||||
## Риски и меры по их снижению
|
||||
|
||||
| Риск | Влияние | Меры по снижению |
|
||||
|------|--------|------------|
|
||||
| Изменения, нарушающие работу пользователей | Высокое | Реализовать период обратной совместимости |
|
||||
| Спутанность конфигурации во время перехода | Среднее | Четкая документация и предупреждения об устаревании |
|
||||
| Сбои в тестах | Среднее | Комплексное обновление тестов |
|
||||
| Проблемы при развертывании Docker | Высокое | Обновить все примеры Docker Compose |
|
||||
|
||||
## Критерии успеха
|
||||
|
||||
[ ] Все модули используют согласованные имена параметров `cassandra_*`
|
||||
[ ] Все процессоры предоставляют настройки Cassandra через аргументы командной строки
|
||||
[ ] Текстовая справка по командной строке показывает значения переменных окружения по умолчанию
|
||||
[ ] Значения паролей никогда не отображаются в справке
|
||||
[ ] Механизм отката к переменным окружения работает правильно
|
||||
[ ] `cassandra_host` последовательно обрабатывается как список внутри
|
||||
[ ] Обратная совместимость поддерживается не менее 2 версий
|
||||
[ ] Все тесты проходят с новой системой конфигурации
|
||||
[ ] Документация полностью обновлена
|
||||
[ ] Примеры Docker Compose работают с переменными окружения
|
||||
|
||||
## План
|
||||
|
||||
**Неделя 1:** Реализовать общий помощник конфигурации и обновить модули `graph_*`
|
||||
**Неделя 2:** Добавить поддержку переменных окружения в существующие модули `cassandra_*`
|
||||
**Неделя 3:** Обновить тесты и документацию
|
||||
**Неделя 4:** Интеграционное тестирование и исправление ошибок
|
||||
|
||||
## Будущие соображения
|
||||
|
||||
Рассмотреть возможность расширения этой модели на другие конфигурации баз данных (например, Elasticsearch)
|
||||
Реализовать проверку конфигурации и улучшенные сообщения об ошибках
|
||||
Добавить поддержку конфигурации пула соединений Cassandra
|
||||
Рассмотреть возможность добавления поддержки файлов конфигурации (.env)
|
||||
339
docs/tech-specs/cassandra-consolidation.sw.md
Normal file
339
docs/tech-specs/cassandra-consolidation.sw.md
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Maelekezo ya Kisaikolojia: Uunganishaji wa Vipengele vya Usanidi wa Cassandra"
|
||||
parent: "Swahili (Beta)"
|
||||
---
|
||||
|
||||
# Maelekezo ya Kisaikolojia: Uunganishaji wa Vipengele vya Usanidi wa Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**Hali:** Rasimu
|
||||
**Mwandishi:** Msaidizi
|
||||
**Tarehe:** 2024-09-03
|
||||
|
||||
## Muhtasari
|
||||
|
||||
Maelekezo haya yanashughulikia utofauti katika majina na mifumo ya usanidi kwa vigezo vya muunganisho wa Cassandra katika mfumo wa TrustGraph. Kwa sasa, mifumo miwili tofauti ya majina ya vigezo ipo (`cassandra_*` vs `graph_*`), ambayo husababisha mchanganyiko na ugumu wa matengenezo.
|
||||
|
||||
## Tatizo
|
||||
|
||||
Mfumo wa programu hutumia seti mbili tofauti za vigezo vya usanidi wa Cassandra:
|
||||
|
||||
1. **Moduli za /Config/Library za Maarifa** hutumia:
|
||||
`cassandra_host` (orodha ya seva)
|
||||
`cassandra_user`
|
||||
`cassandra_password`
|
||||
|
||||
2. **Moduli za /Storage za Grafu** hutumia:
|
||||
`graph_host` (seva moja, wakati mwingine hubadilishwa kuwa orodha)
|
||||
`graph_username`
|
||||
`graph_password`
|
||||
|
||||
3. **Uonyeshaji usio sawa wa amri:**
|
||||
Baadhi ya vichakata (e.g., `kg-store`) hazionyeshi mipangilio ya Cassandra kama hoja za amri
|
||||
Vichakata vingine huonyesha kwa majina na muundo tofauti
|
||||
Nakala ya usaidizi haionyeshi maadili chaguo-msingi ya vigezo vya mazingira
|
||||
|
||||
Seti zote mbili za vigezo zinaunganisha na kundi sawa la Cassandra lakini kwa mikataba tofauti ya majina, na kusababisha:
|
||||
Mchanganyiko wa usanidi kwa watumiaji
|
||||
Ongezeko la mzigo wa matengenezo
|
||||
Nyaraka zisizo sawa
|
||||
Uwezekano wa usanidi usio sahihi
|
||||
Uwezo wa kutofanya ubadilishaji wa mipangilio kupitia hoja za amri katika vichakata vingine
|
||||
|
||||
## Suluhisho Lililopendekezwa
|
||||
|
||||
### 1. Kuweka Majina ya Vigezo
|
||||
|
||||
Moduli zote zitatumia majina sawa ya vigezo ya `cassandra_*`:
|
||||
`cassandra_host` - Orodha ya seva (hifadhiwa ndani kama orodha)
|
||||
`cassandra_username` - Jina la mtumiaji kwa uthibitishaji
|
||||
`cassandra_password` - Nenosiri kwa uthibitishaji
|
||||
|
||||
### 2. Hoja za Amri
|
||||
|
||||
Vichakata vyote WILIVYO na kuonyesha usanidi wa Cassandra kupitia hoja za amri:
|
||||
`--cassandra-host` - Orodha iliyoachwa na alama ya mwelekeo wa koma ya seva
|
||||
`--cassandra-username` - Jina la mtumiaji kwa uthibitishaji
|
||||
`--cassandra-password` - Nenosiri kwa uthibitishaji
|
||||
|
||||
### 3. Usaidizi wa Vigezo vya Mazingira
|
||||
|
||||
Ikiwa hoja za amri hazitolewi wazi, mfumo utangalia vigezo vya mazingira:
|
||||
`CASSANDRA_HOST` - Orodha iliyoachwa na alama ya mwelekeo wa koma ya seva
|
||||
`CASSANDRA_USERNAME` - Jina la mtumiaji kwa uthibitishaji
|
||||
`CASSANDRA_PASSWORD` - Nenosiri kwa uthibitishaji
|
||||
|
||||
### 4. Maadili Chaguo-msingi
|
||||
|
||||
Ikiwa hoja za amri wala vigezo vya mazingira hazibainishwi:
|
||||
`cassandra_host` huanguka kwenye `["cassandra"]`
|
||||
`cassandra_username` huanguka kwenye `None` (hakuna uthibitishaji)
|
||||
`cassandra_password` huanguka kwenye `None` (hakuna uthibitishaji)
|
||||
|
||||
### 5. Mahitaji ya Nakala ya Usaidizi
|
||||
|
||||
Pato la `--help` lazima:
|
||||
Kuonyesha maadili ya vigezo vya mazingira kama chaguo-msingi wakati yamepangwa
|
||||
Kamwe kuonyesha maadili ya nenosiri (onyesha `****` au `<set>` badala yake)
|
||||
Kuonyesha wazi utaratibu wa utatuzi katika nakala ya usaidizi
|
||||
|
||||
Mfano wa pato la usaidizi:
|
||||
```
|
||||
--cassandra-host HOST
|
||||
Cassandra host list, comma-separated (default: prod-cluster-1,prod-cluster-2)
|
||||
[from CASSANDRA_HOST environment variable]
|
||||
|
||||
--cassandra-username USERNAME
|
||||
Cassandra username (default: cassandra_user)
|
||||
[from CASSANDRA_USERNAME environment variable]
|
||||
|
||||
--cassandra-password PASSWORD
|
||||
Cassandra password (default: <set from environment>)
|
||||
```
|
||||
|
||||
## Maelezo ya Utendaji
|
||||
|
||||
### Utaratibu wa Uamuzi wa Vigezo
|
||||
|
||||
Kwa kila kiparamu cha Cassandra, utaratibu wa uamuzi utakuwa:
|
||||
1. Thamani ya hoja ya mstari wa amri
|
||||
2. Kigezo cha mazingira (`CASSANDRA_*`)
|
||||
3. Thamani chaguo-msingi
|
||||
|
||||
### Usimamizi wa Kiparamu cha Host
|
||||
|
||||
Kiparamu cha `cassandra_host`:
|
||||
Mstari wa amri unapokea mnyororo ulioachiliwa na alama ya kung'aa: `--cassandra-host "host1,host2,host3"`
|
||||
Kigezo cha mazingira kinapokea mnyororo ulioachiliwa na alama ya kung'aa: `CASSANDRA_HOST="host1,host2,host3"`
|
||||
Daima kuhifadhiwa kama orodha ndani: `["host1", "host2", "host3"]`
|
||||
Host moja: `"localhost"` → inabadilishwa kuwa `["localhost"]`
|
||||
Tayari ni orodha: `["host1", "host2"]` → inatumika kama ilivyo
|
||||
|
||||
### Mantiki ya Uthibitisho
|
||||
|
||||
Uthibitisho utatumika wakati `cassandra_username` na `cassandra_password` zote zimetolewa:
|
||||
```python
|
||||
if cassandra_username and cassandra_password:
|
||||
# Use SSL context and PlainTextAuthProvider
|
||||
else:
|
||||
# Connect without authentication
|
||||
```
|
||||
|
||||
## Faili Zinazohitaji Marekebisho
|
||||
|
||||
### Moduli zinazotumia vigezo vya `graph_*` (zinazohitaji kubadilishwa):
|
||||
`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/rows/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
|
||||
### Moduli zinazotumia vigezo vya `cassandra_*` (zinazohitaji kusasishwa na chaguo-msingi la mazingira):
|
||||
`trustgraph-flow/trustgraph/tables/config.py`
|
||||
`trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/tables/library.py`
|
||||
`trustgraph-flow/trustgraph/storage/knowledge/store.py`
|
||||
`trustgraph-flow/trustgraph/cores/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/librarian/librarian.py`
|
||||
`trustgraph-flow/trustgraph/librarian/service.py`
|
||||
`trustgraph-flow/trustgraph/config/service/service.py`
|
||||
`trustgraph-flow/trustgraph/cores/service.py`
|
||||
|
||||
### Faili za Majaribio Zinazohitaji Kusasishwa:
|
||||
`tests/unit/test_cores/test_knowledge_manager.py`
|
||||
`tests/unit/test_storage/test_triples_cassandra_storage.py`
|
||||
`tests/unit/test_query/test_triples_cassandra_query.py`
|
||||
`tests/integration/test_objects_cassandra_integration.py`
|
||||
|
||||
## Mbinu ya Utendaji
|
||||
|
||||
### Hatua ya 1: Unda Msaidizi wa Mpangilio wa Msingi
|
||||
Unda kazi za matumizi ili kuhakikisha mpangilio wa Cassandra ni sawa katika vichakata vyote:
|
||||
|
||||
```python
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def get_cassandra_defaults():
|
||||
"""Get default values from environment variables or fallback."""
|
||||
return {
|
||||
'host': os.getenv('CASSANDRA_HOST', 'cassandra'),
|
||||
'username': os.getenv('CASSANDRA_USERNAME'),
|
||||
'password': os.getenv('CASSANDRA_PASSWORD')
|
||||
}
|
||||
|
||||
def add_cassandra_args(parser: argparse.ArgumentParser):
|
||||
"""
|
||||
Add standardized Cassandra arguments to an argument parser.
|
||||
Shows environment variable values in help text.
|
||||
"""
|
||||
defaults = get_cassandra_defaults()
|
||||
|
||||
# Format help text with env var indication
|
||||
host_help = f"Cassandra host list, comma-separated (default: {defaults['host']})"
|
||||
if 'CASSANDRA_HOST' in os.environ:
|
||||
host_help += " [from CASSANDRA_HOST]"
|
||||
|
||||
username_help = f"Cassandra username"
|
||||
if defaults['username']:
|
||||
username_help += f" (default: {defaults['username']})"
|
||||
if 'CASSANDRA_USERNAME' in os.environ:
|
||||
username_help += " [from CASSANDRA_USERNAME]"
|
||||
|
||||
password_help = "Cassandra password"
|
||||
if defaults['password']:
|
||||
password_help += " (default: <set>)"
|
||||
if 'CASSANDRA_PASSWORD' in os.environ:
|
||||
password_help += " [from CASSANDRA_PASSWORD]"
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-host',
|
||||
default=defaults['host'],
|
||||
help=host_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-username',
|
||||
default=defaults['username'],
|
||||
help=username_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-password',
|
||||
default=defaults['password'],
|
||||
help=password_help
|
||||
)
|
||||
|
||||
def resolve_cassandra_config(args) -> tuple[list[str], str|None, str|None]:
|
||||
"""
|
||||
Convert argparse args to Cassandra configuration.
|
||||
|
||||
Returns:
|
||||
tuple: (hosts_list, username, password)
|
||||
"""
|
||||
# Convert host string to list
|
||||
if isinstance(args.cassandra_host, str):
|
||||
hosts = [h.strip() for h in args.cassandra_host.split(',')]
|
||||
else:
|
||||
hosts = args.cassandra_host
|
||||
|
||||
return hosts, args.cassandra_username, args.cassandra_password
|
||||
```
|
||||
|
||||
### Awamu ya 2: Sasisha Moduli Ukitumia Vigezo vya `graph_*`
|
||||
1. Badilisha majina ya vigezo kutoka `graph_*` hadi `cassandra_*`
|
||||
2. Badilisha mbinu (methods) maalum za `add_args()` kwa mbinu za kawaida za `add_cassandra_args()`
|
||||
3. Tumia kazi (functions) za kawaida za usaidizi wa usanidi
|
||||
4. Sasisha maandishi ya utangazaji (documentation strings)
|
||||
|
||||
Mfano wa mabadiliko:
|
||||
```python
|
||||
# OLD CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
parser.add_argument(
|
||||
'-g', '--graph-host',
|
||||
default="localhost",
|
||||
help=f'Graph host (default: localhost)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--graph-username',
|
||||
default=None,
|
||||
help=f'Cassandra username'
|
||||
)
|
||||
|
||||
# NEW CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
FlowProcessor.add_args(parser)
|
||||
add_cassandra_args(parser) # Use standard helper
|
||||
```
|
||||
|
||||
### Awamu ya 3: Sasisha Moduli Ukitumia Vigezo vya `cassandra_*`
|
||||
1. Ongeza uunganisha wa hoja za mstari wa amri ambapo haipo (k.m., `kg-store`)
|
||||
2. Badilisha ufafanuzi wa hoja zilizopo kwa `add_cassandra_args()`
|
||||
3. Tumia `resolve_cassandra_config()` kwa utaratibu thabiti
|
||||
4. Hakikisha utunzaji thabiti wa orodha ya seva
|
||||
|
||||
### Awamu ya 4: Sasisha Vipimo na Nyaraka
|
||||
1. Sasisha faili zote za vipimo ili zitumie majina mapya ya vigezo
|
||||
2. Sasisha nyaraka za CLI
|
||||
3. Sasisha nyaraka za API
|
||||
4. Ongeza nyaraka za vigezo vya mazingira
|
||||
|
||||
## Ulinganishaji na Mifumo ya Zamani
|
||||
|
||||
Ili kudumisha ulinganishaji na mifumo ya zamani wakati wa mabadiliko:
|
||||
|
||||
1. **Maonyo ya kutolewa nje** kwa vigezo vya `graph_*`
|
||||
2. **Ujumuishaji wa vigezo** - kukubali majina ya zamani na mapya awali
|
||||
3. **Utoaji wa hatua kwa hatua** katika matoleo mengi
|
||||
4. **Sasisho za nyaraka** pamoja na mwongozo wa uhamishaji
|
||||
|
||||
Mfano wa msimbo wa ulinganishaji na mifumo ya zamani:
|
||||
```python
|
||||
def __init__(self, **params):
|
||||
# Handle deprecated graph_* parameters
|
||||
if 'graph_host' in params:
|
||||
warnings.warn("graph_host is deprecated, use cassandra_host", DeprecationWarning)
|
||||
params.setdefault('cassandra_host', params.pop('graph_host'))
|
||||
|
||||
if 'graph_username' in params:
|
||||
warnings.warn("graph_username is deprecated, use cassandra_username", DeprecationWarning)
|
||||
params.setdefault('cassandra_username', params.pop('graph_username'))
|
||||
|
||||
# ... continue with standard resolution
|
||||
```
|
||||
|
||||
## Mbinu ya Majaribio
|
||||
|
||||
1. **Majaribio ya kitengo** kwa mantiki ya utatuzi wa usanidi
|
||||
2. **Majaribio ya ujumuishaji** na mchanganyiko mbalimbali wa usanidi
|
||||
3. **Majaribio ya vigezo vya mazingira**
|
||||
4. **Majaribio ya utangamano wa nyuma** na vigezo vilivyotolewa
|
||||
5. **Majaribio ya Docker compose** na vigezo vya mazingira
|
||||
|
||||
## Sasisho za Nyaraka
|
||||
|
||||
1. Sasisha nyaraka zote za amri za CLI
|
||||
2. Sasisha nyaraka za API
|
||||
3. Unda mwongozo wa uhamishaji
|
||||
4. Sasisha mifano ya Docker compose
|
||||
5. Sasisha nyaraka za kumbukumbu ya usanidi
|
||||
|
||||
## Hatari na Kupunguza Madhara
|
||||
|
||||
| Hatari | Athari | Kupunguza Madhara |
|
||||
|------|--------|------------|
|
||||
| Mabadiliko yanayoweza kusababisha matatizo kwa watumiaji | Ya juu | Tekeleza kipindi cha utangamano wa nyuma |
|
||||
| Uchanganyifu wa usanidi wakati wa mabadiliko | Ya kati | Nyaraka wazi na onyo la kutolewa |
|
||||
| Kushindwa kwa majaribio | Ya kati | Sasisho kamili ya majaribio |
|
||||
| Matatizo ya usakinishaji wa Docker | Ya juu | Sasisha mifano yote ya Docker compose |
|
||||
|
||||
## Vigezo vya Mafanikio
|
||||
|
||||
[ ] Moduli zote hutumia majina ya vigezo `cassandra_*` yanayofanana
|
||||
[ ] Wasindikaji wote huonyesha mipangilio ya Cassandra kupitia hoja za mstari wa amri
|
||||
[ ] Nakala ya msaada wa mstari wa amri inaonyesha chaguo-msingi ya vigezo vya mazingira
|
||||
[ ] Maelezo ya nenosiri hayajaonyeshwa katika nakala ya msaada
|
||||
[ ] Mfumo wa kurudisha nyuma wa vigezo vya mazingira unafanya kazi vizuri
|
||||
[ ] `cassandra_host` inashughulikiwa kwa utaratibu kama orodha ndani
|
||||
[ ] Utangamano wa nyuma umeendelezwa kwa angalau matoleo 2
|
||||
[ ] Majaribio yote hupita na mfumo mpya wa usanidi
|
||||
[ ] Nyaraka zimesasishwa kikamilifu
|
||||
[ ] Mifano ya Docker compose inafanya kazi na vigezo vya mazingira
|
||||
|
||||
## Ratiba
|
||||
|
||||
**Wiki ya 1:** Tekeleza kusaidia usanidi wa kawaida na sasisha moduli za `graph_*`
|
||||
**Wiki ya 2:** Ongeza usaidizi wa vigezo vya mazingira kwa moduli zilizopo za `cassandra_*`
|
||||
**Wiki ya 3:** Sasisha majaribio na nyaraka
|
||||
**Wiki ya 4:** Majaribio ya ujumuishaji na urekebishaji wa hitilafu
|
||||
|
||||
## Mambo ya Kuzingatia ya Baadaye
|
||||
|
||||
Fikiria kuongeza muundo huu kwa usanidi mwingine wa hifadhidata (e.g., Elasticsearch)
|
||||
Tekeleza uthibitisho wa usanidi na ujumbe bora wa kosa
|
||||
Ongeza usaidizi wa usanidi wa muunganisho wa Cassandra (e.g., pooli)
|
||||
Fikiria kuongeza usaidizi wa faili za usanidi (.env files)
|
||||
339
docs/tech-specs/cassandra-consolidation.tr.md
Normal file
339
docs/tech-specs/cassandra-consolidation.tr.md
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Cassandra Yapılandırma Birleştirme: Teknik Özellikler"
|
||||
parent: "Turkish (Beta)"
|
||||
---
|
||||
|
||||
# Cassandra Yapılandırma Birleştirme: Teknik Özellikler
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**Durum:** Taslak
|
||||
**Yazar:** Yardımcı
|
||||
**Tarih:** 2024-09-03
|
||||
|
||||
## Genel Bakış
|
||||
|
||||
Bu özellik, TrustGraph kod tabanındaki Cassandra bağlantı parametreleri için tutarsız adlandırma ve yapılandırma kalıplarını ele almaktadır. Şu anda, iki farklı parametre adlandırma şeması bulunmaktadır (`cassandra_*` ve `graph_*`), bu da kafa karışıklığına ve bakım karmaşıklığına yol açmaktadır.
|
||||
|
||||
## Sorun Tanımı
|
||||
|
||||
Kod tabanı şu anda iki farklı Cassandra yapılandırma parametre seti kullanmaktadır:
|
||||
|
||||
1. **Bilgi/Yapılandırma/Kütüphane modülleri** aşağıdaki parametreleri kullanır:
|
||||
`cassandra_host` (sunucu listesi)
|
||||
`cassandra_user`
|
||||
`cassandra_password`
|
||||
|
||||
2. **Grafik/Depolama modülleri** aşağıdaki parametreleri kullanır:
|
||||
`graph_host` (tek bir sunucu, bazen listeye dönüştürülür)
|
||||
`graph_username`
|
||||
`graph_password`
|
||||
|
||||
3. **Tutarsız komut satırı kullanımı**:
|
||||
Bazı işleme birimleri (örneğin, `kg-store`), Cassandra ayarlarını komut satırı argümanları olarak sunmaz
|
||||
Diğer işleme birimleri bunları farklı adlar ve formatlarla sunar
|
||||
Yardım metni, ortam değişkeni varsayılanlarını yansıtmaz
|
||||
|
||||
Her iki parametre seti de aynı Cassandra kümesine bağlanır, ancak farklı adlandırma kuralları kullanır, bu da şunlara neden olur:
|
||||
Kullanıcılar için yapılandırma karışıklığı
|
||||
Artan bakım yükü
|
||||
Tutarsız dokümantasyon
|
||||
Yanlış yapılandırma riski
|
||||
Bazı işleme birimlerinde ayarları komut satırı aracılığıyla geçersiz kılma imkansızlığı
|
||||
|
||||
## Önerilen Çözüm
|
||||
|
||||
### 1. Parametre Adlarını Standartlaştırın
|
||||
|
||||
Tüm modüller, tutarlı `cassandra_*` parametre adlarını kullanacaktır:
|
||||
`cassandra_host` - Sunucu listesi (içeride liste olarak saklanır)
|
||||
`cassandra_username` - Kimlik doğrulama için kullanıcı adı
|
||||
`cassandra_password` - Kimlik doğrulama için parola
|
||||
|
||||
### 2. Komut Satırı Argümanları
|
||||
|
||||
TÜM işleme birimleri, Cassandra yapılandırmasını komut satırı argümanları aracılığıyla sunmalıdır:
|
||||
`--cassandra-host` - Virgülle ayrılmış sunucu listesi
|
||||
`--cassandra-username` - Kimlik doğrulama için kullanıcı adı
|
||||
`--cassandra-password` - Kimlik doğrulama için parola
|
||||
|
||||
### 3. Ortam Değişkeni Geri Düşüşü
|
||||
|
||||
Komut satırı parametreleri açıkça sağlanmadığında, sistem ortam değişkenlerini kontrol edecektir:
|
||||
`CASSANDRA_HOST` - Virgülle ayrılmış sunucu listesi
|
||||
`CASSANDRA_USERNAME` - Kimlik doğrulama için kullanıcı adı
|
||||
`CASSANDRA_PASSWORD` - Kimlik doğrulama için parola
|
||||
|
||||
### 4. Varsayılan Değerler
|
||||
|
||||
Ne komut satırı parametreleri ne de ortam değişkenleri belirtilmediğinde:
|
||||
`cassandra_host`, `["cassandra"]`'e varsayılan olarak ayarlanır
|
||||
`cassandra_username`, `None`'e (kimlik doğrulama yok) varsayılan olarak ayarlanır
|
||||
`cassandra_password`, `None`'e (kimlik doğrulama yok) varsayılan olarak ayarlanır
|
||||
|
||||
### 5. Yardım Metni Gereksinimleri
|
||||
|
||||
`--help` çıktısı şunları içermelidir:
|
||||
Ortam değişkeni değerleri ayarlandığında, bunları varsayılan değerler olarak göstermelidir
|
||||
Parola değerlerini asla göstermemelidir (bunun yerine `****` veya `<set>` göstermelidir)
|
||||
Çözüm sırasını yardım metninde açıkça belirtmelidir
|
||||
|
||||
Örnek yardım çıktısı:
|
||||
```
|
||||
--cassandra-host HOST
|
||||
Cassandra host list, comma-separated (default: prod-cluster-1,prod-cluster-2)
|
||||
[from CASSANDRA_HOST environment variable]
|
||||
|
||||
--cassandra-username USERNAME
|
||||
Cassandra username (default: cassandra_user)
|
||||
[from CASSANDRA_USERNAME environment variable]
|
||||
|
||||
--cassandra-password PASSWORD
|
||||
Cassandra password (default: <set from environment>)
|
||||
```
|
||||
|
||||
## Uygulama Detayları
|
||||
|
||||
### Parametre Çözümleme Sırası
|
||||
|
||||
Her Cassandra parametresi için, çözümleme sırası aşağıdaki olacaktır:
|
||||
1. Komut satırı argümanı değeri
|
||||
2. Ortam değişkeni (`CASSANDRA_*`)
|
||||
3. Varsayılan değer
|
||||
|
||||
### Ana Bilgisayar Parametreleri Yönetimi
|
||||
|
||||
`cassandra_host` parametresi:
|
||||
Komut satırı, virgülle ayrılmış bir dize kabul eder: `--cassandra-host "host1,host2,host3"`
|
||||
Ortam değişkeni, virgülle ayrılmış bir dize kabul eder: `CASSANDRA_HOST="host1,host2,host3"`
|
||||
İçeride her zaman bir liste olarak saklanır: `["host1", "host2", "host3"]`
|
||||
Tek bir ana bilgisayar: `"localhost"` → `["localhost"]`'e dönüştürülür
|
||||
Zaten bir liste: `["host1", "host2"]` → olduğu gibi kullanılır
|
||||
|
||||
### Kimlik Doğrulama Mantığı
|
||||
|
||||
Kimlik doğrulama, hem `cassandra_username` hem de `cassandra_password` sağlandığında kullanılacaktır:
|
||||
```python
|
||||
if cassandra_username and cassandra_password:
|
||||
# Use SSL context and PlainTextAuthProvider
|
||||
else:
|
||||
# Connect without authentication
|
||||
```
|
||||
|
||||
## Değiştirilecek Dosyalar
|
||||
|
||||
### `graph_*` parametrelerini kullanan modüller (değiştirilecek):
|
||||
`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/rows/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
|
||||
### `cassandra_*` parametrelerini kullanan modüller (ortam değişkeni geri dönüşü ile güncellenecek):
|
||||
`trustgraph-flow/trustgraph/tables/config.py`
|
||||
`trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/tables/library.py`
|
||||
`trustgraph-flow/trustgraph/storage/knowledge/store.py`
|
||||
`trustgraph-flow/trustgraph/cores/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/librarian/librarian.py`
|
||||
`trustgraph-flow/trustgraph/librarian/service.py`
|
||||
`trustgraph-flow/trustgraph/config/service/service.py`
|
||||
`trustgraph-flow/trustgraph/cores/service.py`
|
||||
|
||||
### Güncellenecek Test Dosyaları:
|
||||
`tests/unit/test_cores/test_knowledge_manager.py`
|
||||
`tests/unit/test_storage/test_triples_cassandra_storage.py`
|
||||
`tests/unit/test_query/test_triples_cassandra_query.py`
|
||||
`tests/integration/test_objects_cassandra_integration.py`
|
||||
|
||||
## Uygulama Stratejisi
|
||||
|
||||
### Aşama 1: Ortak Yapılandırma Yardımcı Programı Oluşturma
|
||||
Tüm işlemcilerde Cassandra yapılandırmasını standartlaştırmak için yardımcı işlevler oluşturun:
|
||||
|
||||
```python
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def get_cassandra_defaults():
|
||||
"""Get default values from environment variables or fallback."""
|
||||
return {
|
||||
'host': os.getenv('CASSANDRA_HOST', 'cassandra'),
|
||||
'username': os.getenv('CASSANDRA_USERNAME'),
|
||||
'password': os.getenv('CASSANDRA_PASSWORD')
|
||||
}
|
||||
|
||||
def add_cassandra_args(parser: argparse.ArgumentParser):
|
||||
"""
|
||||
Add standardized Cassandra arguments to an argument parser.
|
||||
Shows environment variable values in help text.
|
||||
"""
|
||||
defaults = get_cassandra_defaults()
|
||||
|
||||
# Format help text with env var indication
|
||||
host_help = f"Cassandra host list, comma-separated (default: {defaults['host']})"
|
||||
if 'CASSANDRA_HOST' in os.environ:
|
||||
host_help += " [from CASSANDRA_HOST]"
|
||||
|
||||
username_help = f"Cassandra username"
|
||||
if defaults['username']:
|
||||
username_help += f" (default: {defaults['username']})"
|
||||
if 'CASSANDRA_USERNAME' in os.environ:
|
||||
username_help += " [from CASSANDRA_USERNAME]"
|
||||
|
||||
password_help = "Cassandra password"
|
||||
if defaults['password']:
|
||||
password_help += " (default: <set>)"
|
||||
if 'CASSANDRA_PASSWORD' in os.environ:
|
||||
password_help += " [from CASSANDRA_PASSWORD]"
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-host',
|
||||
default=defaults['host'],
|
||||
help=host_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-username',
|
||||
default=defaults['username'],
|
||||
help=username_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-password',
|
||||
default=defaults['password'],
|
||||
help=password_help
|
||||
)
|
||||
|
||||
def resolve_cassandra_config(args) -> tuple[list[str], str|None, str|None]:
|
||||
"""
|
||||
Convert argparse args to Cassandra configuration.
|
||||
|
||||
Returns:
|
||||
tuple: (hosts_list, username, password)
|
||||
"""
|
||||
# Convert host string to list
|
||||
if isinstance(args.cassandra_host, str):
|
||||
hosts = [h.strip() for h in args.cassandra_host.split(',')]
|
||||
else:
|
||||
hosts = args.cassandra_host
|
||||
|
||||
return hosts, args.cassandra_username, args.cassandra_password
|
||||
```
|
||||
|
||||
### 2. Aşama: `graph_*` Parametrelerini Kullanan Modülleri Güncelleme
|
||||
1. Parametre adlarını `graph_*`'dan `cassandra_*`'e değiştirin.
|
||||
2. Özel `add_args()` yöntemlerini standart `add_cassandra_args()` yöntemleriyle değiştirin.
|
||||
3. Ortak yapılandırma yardımcı fonksiyonlarını kullanın.
|
||||
4. Dokümantasyon metinlerini güncelleyin.
|
||||
|
||||
Örnek dönüşüm:
|
||||
```python
|
||||
# OLD CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
parser.add_argument(
|
||||
'-g', '--graph-host',
|
||||
default="localhost",
|
||||
help=f'Graph host (default: localhost)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--graph-username',
|
||||
default=None,
|
||||
help=f'Cassandra username'
|
||||
)
|
||||
|
||||
# NEW CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
FlowProcessor.add_args(parser)
|
||||
add_cassandra_args(parser) # Use standard helper
|
||||
```
|
||||
|
||||
### 3. Aşama: `cassandra_*` Parametrelerini Kullanarak Modülleri Güncelleme
|
||||
1. Eksik olan yerlerde komut satırı argümanı desteğini ekleyin (örneğin, `kg-store`)
|
||||
2. Mevcut argüman tanımlarını `add_cassandra_args()` ile değiştirin
|
||||
3. Tutarlı çözümleme için `resolve_cassandra_config()`'ı kullanın
|
||||
4. Tutarlı ana bilgisayar listesi işleme sağlayın
|
||||
|
||||
### 4. Aşama: Testleri ve Belgeleri Güncelleme
|
||||
1. Tüm test dosyalarını yeni parametre adlarını kullanacak şekilde güncelleyin
|
||||
2. Komut satırı (CLI) belgelerini güncelleyin
|
||||
3. API belgelerini güncelleyin
|
||||
4. Ortam değişkeni belgelerini ekleyin
|
||||
|
||||
## Geriye Dönük Uyumluluk
|
||||
|
||||
Geçiş sırasında geriye dönük uyumluluğu korumak için:
|
||||
|
||||
1. `graph_*` parametreleri için **kullanımdan kaldırma uyarıları**
|
||||
2. **Parametre takma adları** - başlangıçta hem eski hem de yeni adları kabul edin
|
||||
3. **Aşamalı dağıtım** birden fazla sürümde
|
||||
4. **Belge güncellemeleri** ve geçiş kılavuzu
|
||||
|
||||
Örnek geriye dönük uyumluluk kodu:
|
||||
```python
|
||||
def __init__(self, **params):
|
||||
# Handle deprecated graph_* parameters
|
||||
if 'graph_host' in params:
|
||||
warnings.warn("graph_host is deprecated, use cassandra_host", DeprecationWarning)
|
||||
params.setdefault('cassandra_host', params.pop('graph_host'))
|
||||
|
||||
if 'graph_username' in params:
|
||||
warnings.warn("graph_username is deprecated, use cassandra_username", DeprecationWarning)
|
||||
params.setdefault('cassandra_username', params.pop('graph_username'))
|
||||
|
||||
# ... continue with standard resolution
|
||||
```
|
||||
|
||||
## Test Stratejisi
|
||||
|
||||
1. **Birim testleri**, yapılandırma çözümleme mantığı için
|
||||
2. **Entegrasyon testleri**, çeşitli yapılandırma kombinasyonlarıyla
|
||||
3. **Ortam değişkeni testleri**
|
||||
4. **Geriye dönük uyumluluk testleri**, kullanımdan kaldırılmış parametrelerle
|
||||
5. **Docker compose testleri**, ortam değişkenleriyle
|
||||
|
||||
## Dokümantasyon Güncellemeleri
|
||||
|
||||
1. Tüm CLI komutu dokümantasyonunu güncelleyin
|
||||
2. API dokümantasyonunu güncelleyin
|
||||
3. Geçiş kılavuzu oluşturun
|
||||
4. Docker compose örneklerini güncelleyin
|
||||
5. Yapılandırma referans dokümantasyonunu güncelleyin
|
||||
|
||||
## Riskler ve Azaltma
|
||||
|
||||
| Risk | Etki | Azaltma |
|
||||
|------|--------|------------|
|
||||
| Kullanıcılar için bozucu değişiklikler | Yüksek | Geriye dönük uyumluluk süresi uygulayın |
|
||||
| Geçiş sırasında yapılandırma karışıklığı | Orta | Açık dokümantasyon ve kullanımdan kaldırma uyarıları |
|
||||
| Test hataları | Orta | Kapsamlı test güncellemeleri |
|
||||
| Docker dağıtım sorunları | Yüksek | Tüm Docker compose örneklerini güncelleyin |
|
||||
|
||||
## Başarı Kriterleri
|
||||
|
||||
[ ] Tüm modüller, tutarlı `cassandra_*` parametre adlarını kullanır
|
||||
[ ] Tüm işlemciler, Cassandra ayarlarını komut satırı argümanları aracılığıyla sunar
|
||||
[ ] Komut satırı yardım metni, ortam değişkeni varsayılanlarını gösterir
|
||||
[ ] Parola değerleri, yardım metninde asla görüntülenmez
|
||||
[ ] Ortam değişkeni yedeklemesi doğru şekilde çalışır
|
||||
[ ] `cassandra_host`, dahili olarak tutarlı bir şekilde bir liste olarak işlenir
|
||||
[ ] Geriye dönüştürülebilirlik, en az 2 sürüm için korunur
|
||||
[ ] Tüm testler, yeni yapılandırma sistemiyle geçer
|
||||
[ ] Dokümantasyon tamamen güncellenmiştir
|
||||
[ ] Docker compose örnekleri, ortam değişkenleriyle çalışır
|
||||
|
||||
## Zaman Çizelgesi
|
||||
|
||||
**1. Hafta:** Ortak yapılandırma yardımcı programını uygulayın ve `graph_*` modüllerini güncelleyin
|
||||
**2. Hafta:** Mevcut `cassandra_*` modüllerine ortam değişkeni desteği ekleyin
|
||||
**3. Hafta:** Testleri ve dokümantasyonu güncelleyin
|
||||
**4. Hafta:** Entegrasyon testi ve hata düzeltmeleri
|
||||
|
||||
## Gelecek Hususlar
|
||||
|
||||
Bu kalıbı diğer veritabanı yapılandırmalarına (örneğin, Elasticsearch) genişletmeyi düşünün
|
||||
Yapılandırma doğrulama ve daha iyi hata mesajları uygulayın
|
||||
Cassandra bağlantı havuzu yapılandırması desteği ekleyin
|
||||
Yapılandırma dosyası desteği eklemeyi düşünün (.env dosyaları)
|
||||
339
docs/tech-specs/cassandra-consolidation.zh-cn.md
Normal file
339
docs/tech-specs/cassandra-consolidation.zh-cn.md
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
---
|
||||
layout: default
|
||||
title: "技术规范:Cassandra 配置整合"
|
||||
parent: "Chinese (Beta)"
|
||||
---
|
||||
|
||||
# 技术规范:Cassandra 配置整合
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**状态:** 草稿
|
||||
**作者:** 助理
|
||||
**日期:** 2024-09-03
|
||||
|
||||
## 概述
|
||||
|
||||
本规范旨在解决 TrustGraph 代码库中 Cassandra 连接参数命名和配置模式的不一致问题。目前,存在两种不同的参数命名方案(`cassandra_*` 与 `graph_*`),这导致了混乱和维护复杂性。
|
||||
|
||||
## 问题陈述
|
||||
|
||||
当前代码库使用两组不同的 Cassandra 配置参数:
|
||||
|
||||
1. **知识/配置/库模块** 使用:
|
||||
`cassandra_host` (主机列表)
|
||||
`cassandra_user`
|
||||
`cassandra_password`
|
||||
|
||||
2. **图/存储模块** 使用:
|
||||
`graph_host` (单个主机,有时转换为列表)
|
||||
`graph_username`
|
||||
`graph_password`
|
||||
|
||||
3. **命令行暴露不一致:**
|
||||
一些处理器(例如,`kg-store`)不将 Cassandra 设置作为命令行参数暴露
|
||||
其他处理器以不同的名称和格式暴露这些设置
|
||||
帮助文本未反映环境变量的默认值
|
||||
|
||||
这两组参数都连接到同一个 Cassandra 集群,但使用不同的命名约定,导致:
|
||||
用户配置混乱
|
||||
维护负担增加
|
||||
文档不一致
|
||||
可能出现配置错误
|
||||
在某些处理器中,无法通过命令行覆盖设置
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 1. 标准化参数名称
|
||||
|
||||
所有模块都将使用一致的 `cassandra_*` 参数名称:
|
||||
`cassandra_host` - 主机列表(内部存储为列表)
|
||||
`cassandra_username` - 身份验证用户名
|
||||
`cassandra_password` - 身份验证密码
|
||||
|
||||
### 2. 命令行参数
|
||||
|
||||
所有处理器都必须通过命令行参数暴露 Cassandra 配置:
|
||||
`--cassandra-host` - 逗号分隔的主机列表
|
||||
`--cassandra-username` - 身份验证用户名
|
||||
`--cassandra-password` - 身份验证密码
|
||||
|
||||
### 3. 环境变量回退
|
||||
|
||||
如果未显式提供命令行参数,系统将检查环境变量:
|
||||
`CASSANDRA_HOST` - 逗号分隔的主机列表
|
||||
`CASSANDRA_USERNAME` - 身份验证用户名
|
||||
`CASSANDRA_PASSWORD` - 身份验证密码
|
||||
|
||||
### 4. 默认值
|
||||
|
||||
如果未指定命令行参数或环境变量:
|
||||
`cassandra_host` 默认为 `["cassandra"]`
|
||||
`cassandra_username` 默认为 `None` (无身份验证)
|
||||
`cassandra_password` 默认为 `None` (无身份验证)
|
||||
|
||||
### 5. 帮助文本要求
|
||||
|
||||
`--help` 输出必须:
|
||||
显示已设置的环境变量值作为默认值
|
||||
绝不显示密码值(显示 `****` 或 `<set>` 代替)
|
||||
在帮助文本中清楚地指示解析顺序
|
||||
|
||||
示例帮助输出:
|
||||
```
|
||||
--cassandra-host HOST
|
||||
Cassandra host list, comma-separated (default: prod-cluster-1,prod-cluster-2)
|
||||
[from CASSANDRA_HOST environment variable]
|
||||
|
||||
--cassandra-username USERNAME
|
||||
Cassandra username (default: cassandra_user)
|
||||
[from CASSANDRA_USERNAME environment variable]
|
||||
|
||||
--cassandra-password PASSWORD
|
||||
Cassandra password (default: <set from environment>)
|
||||
```
|
||||
|
||||
## 实现细节
|
||||
|
||||
### 参数解析顺序
|
||||
|
||||
对于每个 Cassandra 参数,解析顺序如下:
|
||||
1. 命令行参数值
|
||||
2. 环境变量 (`CASSANDRA_*`)
|
||||
3. 默认值
|
||||
|
||||
### 主机参数处理
|
||||
|
||||
`cassandra_host` 参数:
|
||||
命令行接受逗号分隔的字符串:`--cassandra-host "host1,host2,host3"`
|
||||
环境变量接受逗号分隔的字符串:`CASSANDRA_HOST="host1,host2,host3"`
|
||||
内部始终存储为列表:`["host1", "host2", "host3"]`
|
||||
单个主机:`"localhost"` → 转换为 `["localhost"]`
|
||||
已经是列表:`["host1", "host2"]` → 保持原样
|
||||
|
||||
### 认证逻辑
|
||||
|
||||
当同时提供 `cassandra_username` 和 `cassandra_password` 时,将使用认证:
|
||||
```python
|
||||
if cassandra_username and cassandra_password:
|
||||
# Use SSL context and PlainTextAuthProvider
|
||||
else:
|
||||
# Connect without authentication
|
||||
```
|
||||
|
||||
## 需要修改的文件
|
||||
|
||||
### 使用 `graph_*` 参数的模块(需要修改):
|
||||
`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/rows/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
|
||||
### 使用 `cassandra_*` 参数的模块(需要更新,并使用环境变量回退):
|
||||
`trustgraph-flow/trustgraph/tables/config.py`
|
||||
`trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/tables/library.py`
|
||||
`trustgraph-flow/trustgraph/storage/knowledge/store.py`
|
||||
`trustgraph-flow/trustgraph/cores/knowledge.py`
|
||||
`trustgraph-flow/trustgraph/librarian/librarian.py`
|
||||
`trustgraph-flow/trustgraph/librarian/service.py`
|
||||
`trustgraph-flow/trustgraph/config/service/service.py`
|
||||
`trustgraph-flow/trustgraph/cores/service.py`
|
||||
|
||||
### 需要更新的测试文件:
|
||||
`tests/unit/test_cores/test_knowledge_manager.py`
|
||||
`tests/unit/test_storage/test_triples_cassandra_storage.py`
|
||||
`tests/unit/test_query/test_triples_cassandra_query.py`
|
||||
`tests/integration/test_objects_cassandra_integration.py`
|
||||
|
||||
## 实施策略
|
||||
|
||||
### 第一阶段:创建通用的配置辅助工具
|
||||
创建实用函数,以标准化所有处理器中的 Cassandra 配置:
|
||||
|
||||
```python
|
||||
import os
|
||||
import argparse
|
||||
|
||||
def get_cassandra_defaults():
|
||||
"""Get default values from environment variables or fallback."""
|
||||
return {
|
||||
'host': os.getenv('CASSANDRA_HOST', 'cassandra'),
|
||||
'username': os.getenv('CASSANDRA_USERNAME'),
|
||||
'password': os.getenv('CASSANDRA_PASSWORD')
|
||||
}
|
||||
|
||||
def add_cassandra_args(parser: argparse.ArgumentParser):
|
||||
"""
|
||||
Add standardized Cassandra arguments to an argument parser.
|
||||
Shows environment variable values in help text.
|
||||
"""
|
||||
defaults = get_cassandra_defaults()
|
||||
|
||||
# Format help text with env var indication
|
||||
host_help = f"Cassandra host list, comma-separated (default: {defaults['host']})"
|
||||
if 'CASSANDRA_HOST' in os.environ:
|
||||
host_help += " [from CASSANDRA_HOST]"
|
||||
|
||||
username_help = f"Cassandra username"
|
||||
if defaults['username']:
|
||||
username_help += f" (default: {defaults['username']})"
|
||||
if 'CASSANDRA_USERNAME' in os.environ:
|
||||
username_help += " [from CASSANDRA_USERNAME]"
|
||||
|
||||
password_help = "Cassandra password"
|
||||
if defaults['password']:
|
||||
password_help += " (default: <set>)"
|
||||
if 'CASSANDRA_PASSWORD' in os.environ:
|
||||
password_help += " [from CASSANDRA_PASSWORD]"
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-host',
|
||||
default=defaults['host'],
|
||||
help=host_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-username',
|
||||
default=defaults['username'],
|
||||
help=username_help
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--cassandra-password',
|
||||
default=defaults['password'],
|
||||
help=password_help
|
||||
)
|
||||
|
||||
def resolve_cassandra_config(args) -> tuple[list[str], str|None, str|None]:
|
||||
"""
|
||||
Convert argparse args to Cassandra configuration.
|
||||
|
||||
Returns:
|
||||
tuple: (hosts_list, username, password)
|
||||
"""
|
||||
# Convert host string to list
|
||||
if isinstance(args.cassandra_host, str):
|
||||
hosts = [h.strip() for h in args.cassandra_host.split(',')]
|
||||
else:
|
||||
hosts = args.cassandra_host
|
||||
|
||||
return hosts, args.cassandra_username, args.cassandra_password
|
||||
```
|
||||
|
||||
### 第二阶段:使用 `graph_*` 参数更新模块
|
||||
1. 将参数名称从 `graph_*` 更改为 `cassandra_*`
|
||||
2. 将自定义 `add_args()` 方法替换为标准化的 `add_cassandra_args()`
|
||||
3. 使用通用的配置辅助函数
|
||||
4. 更新文档字符串
|
||||
|
||||
示例转换:
|
||||
```python
|
||||
# OLD CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
parser.add_argument(
|
||||
'-g', '--graph-host',
|
||||
default="localhost",
|
||||
help=f'Graph host (default: localhost)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--graph-username',
|
||||
default=None,
|
||||
help=f'Cassandra username'
|
||||
)
|
||||
|
||||
# NEW CODE
|
||||
@staticmethod
|
||||
def add_args(parser):
|
||||
FlowProcessor.add_args(parser)
|
||||
add_cassandra_args(parser) # Use standard helper
|
||||
```
|
||||
|
||||
### 第三阶段:使用 `cassandra_*` 参数更新模块
|
||||
1. 在缺失的地方添加命令行参数支持(例如:`kg-store`)
|
||||
2. 将现有的参数定义替换为 `add_cassandra_args()`
|
||||
3. 使用 `resolve_cassandra_config()` 以实现一致的解析
|
||||
4. 确保一致的主机列表处理
|
||||
|
||||
### 第四阶段:更新测试和文档
|
||||
1. 更新所有测试文件以使用新的参数名称
|
||||
2. 更新命令行界面 (CLI) 文档
|
||||
3. 更新 API 文档
|
||||
4. 添加环境变量文档
|
||||
|
||||
## 向后兼容性
|
||||
|
||||
为了在过渡期间保持向后兼容性:
|
||||
|
||||
1. **弃用警告**,用于 `graph_*` 参数
|
||||
2. **参数别名** - 初始阶段接受旧名称和新名称
|
||||
3. **分阶段发布**,在多个版本中进行
|
||||
4. **文档更新**,包含迁移指南
|
||||
|
||||
示例向后兼容代码:
|
||||
```python
|
||||
def __init__(self, **params):
|
||||
# Handle deprecated graph_* parameters
|
||||
if 'graph_host' in params:
|
||||
warnings.warn("graph_host is deprecated, use cassandra_host", DeprecationWarning)
|
||||
params.setdefault('cassandra_host', params.pop('graph_host'))
|
||||
|
||||
if 'graph_username' in params:
|
||||
warnings.warn("graph_username is deprecated, use cassandra_username", DeprecationWarning)
|
||||
params.setdefault('cassandra_username', params.pop('graph_username'))
|
||||
|
||||
# ... continue with standard resolution
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
1. **单元测试**,用于配置解析逻辑
|
||||
2. **集成测试**,使用各种配置组合
|
||||
3. **环境变量测试**
|
||||
4. **向后兼容性测试**,针对已弃用的参数
|
||||
5. **Docker Compose 测试**,使用环境变量
|
||||
|
||||
## 文档更新
|
||||
|
||||
1. 更新所有 CLI 命令文档
|
||||
2. 更新 API 文档
|
||||
3. 创建迁移指南
|
||||
4. 更新 Docker Compose 示例
|
||||
5. 更新配置参考文档
|
||||
|
||||
## 风险与缓解
|
||||
|
||||
| 风险 | 影响 | 缓解措施 |
|
||||
|------|--------|------------|
|
||||
| 对用户的破坏性更改 | 高 | 实施向后兼容性过渡期 |
|
||||
| 转换期间的配置混淆 | 中 | 清晰的文档和弃用警告 |
|
||||
| 测试失败 | 中 | 全面的测试更新 |
|
||||
| Docker 部署问题 | 高 | 更新所有 Docker Compose 示例 |
|
||||
|
||||
## 成功标准
|
||||
|
||||
[ ] 所有模块使用一致的 `cassandra_*` 参数名称
|
||||
[ ] 所有处理器通过命令行参数暴露 Cassandra 设置
|
||||
[ ] 命令行帮助文本显示环境变量的默认值
|
||||
[ ] 密码值绝不在帮助文本中显示
|
||||
[ ] 环境变量回退工作正常
|
||||
[ ] `cassandra_host` 内部始终被处理为列表
|
||||
[ ] 至少在 2 个版本中保持向后兼容性
|
||||
[ ] 所有测试在新配置系统中通过
|
||||
[ ] 文档已完全更新
|
||||
[ ] Docker Compose 示例使用环境变量
|
||||
|
||||
## 时间线
|
||||
|
||||
**第一周:** 实施通用的配置助手,并更新 `graph_*` 模块
|
||||
**第二周:** 为现有的 `cassandra_*` 模块添加环境变量支持
|
||||
**第三周:** 更新测试和文档
|
||||
**第四周:** 集成测试和错误修复
|
||||
|
||||
## 未来考虑
|
||||
|
||||
考虑将此模式扩展到其他数据库配置(例如,Elasticsearch)
|
||||
实施配置验证和更好的错误消息
|
||||
添加对 Cassandra 连接池配置的支持
|
||||
考虑添加对配置文件支持(.env 文件)
|
||||
687
docs/tech-specs/cassandra-performance-refactor.ar.md
Normal file
687
docs/tech-specs/cassandra-performance-refactor.ar.md
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
---
|
||||
layout: default
|
||||
title: "المواصفات الفنية: إعادة هيكلة أداء قاعدة المعرفة Cassandra"
|
||||
parent: "Arabic (Beta)"
|
||||
---
|
||||
|
||||
# المواصفات الفنية: إعادة هيكلة أداء قاعدة المعرفة Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**الحالة:** مسودة
|
||||
**المؤلف:** مساعد
|
||||
**التاريخ:** 2025-09-18
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
تتناول هذه المواصفة مشكلات الأداء في تطبيق قاعدة المعرفة Cassandra TrustGraph وتقترح تحسينات لتخزين واستعلام ثلاثيات RDF.
|
||||
|
||||
## التنفيذ الحالي
|
||||
|
||||
### تصميم المخطط
|
||||
|
||||
يستخدم التنفيذ الحالي تصميم جدول واحد في `trustgraph-flow/trustgraph/direct/cassandra_kg.py`:
|
||||
|
||||
```sql
|
||||
CREATE TABLE triples (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
|
||||
**الفهارس الثانوية:**
|
||||
`triples_s` على `s` (الموضوع)
|
||||
`triples_p` على `p` (المُتَعَدِّي)
|
||||
`triples_o` على `o` (المفعول به)
|
||||
|
||||
### أنماط الاستعلام
|
||||
|
||||
تدعم التنفيذ الحالي 8 أنماط استعلام متميزة:
|
||||
|
||||
1. **get_all(collection, limit=50)** - استرجاع جميع الثلاثيات لمجموعة
|
||||
```sql
|
||||
SELECT s, p, o FROM triples WHERE collection = ? LIMIT 50
|
||||
```
|
||||
|
||||
2. **get_s(collection, s, limit=10)** - الاستعلام بناءً على الموضوع.
|
||||
```sql
|
||||
SELECT p, o FROM triples WHERE collection = ? AND s = ? LIMIT 10
|
||||
```
|
||||
|
||||
3. **get_p(collection, p, limit=10)** - الاستعلام بناءً على شرط.
|
||||
```sql
|
||||
SELECT s, o FROM triples WHERE collection = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
4. **get_o(collection, o, limit=10)** - الاستعلام بناءً على الكائن.
|
||||
```sql
|
||||
SELECT s, p FROM triples WHERE collection = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
5. **get_sp(collection, s, p, limit=10)** - الاستعلام بناءً على الموضوع + المسند.
|
||||
```sql
|
||||
SELECT o FROM triples WHERE collection = ? AND s = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
6. **get_po(collection, p, o, limit=10)** - الاستعلام بناءً على الشرط + الكائن ⚠️
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
7. **get_os(collection, o, s, limit=10)** - الاستعلام بناءً على الكائن والموضوع ⚠️
|
||||
```sql
|
||||
SELECT p FROM triples WHERE collection = ? AND o = ? AND s = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
8. **get_spo(collection, s, p, o, limit=10)** - تطابق ثلاثي دقيق.
|
||||
```sql
|
||||
SELECT s as x FROM triples WHERE collection = ? AND s = ? AND p = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
### البنية التحتية الحالية
|
||||
|
||||
**الملف: `trustgraph-flow/trustgraph/direct/cassandra_kg.py`**
|
||||
فئة `KnowledgeGraph` واحدة تتعامل مع جميع العمليات.
|
||||
تجميع الاتصالات من خلال قائمة `_active_clusters` عامة.
|
||||
اسم جدول ثابت: `"triples"`.
|
||||
مساحة مفاتيح لكل نموذج مستخدم.
|
||||
استنساخ SimpleStrategy بعامل 1.
|
||||
|
||||
**نقاط التكامل:**
|
||||
**مسار الكتابة:** `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`.
|
||||
**مسار الاستعلام:** `trustgraph-flow/trustgraph/query/triples/cassandra/service.py`.
|
||||
**مخزن المعرفة:** `trustgraph-flow/trustgraph/tables/knowledge.py`.
|
||||
|
||||
## المشكلات المتعلقة بالأداء التي تم تحديدها
|
||||
|
||||
### مشكلات على مستوى المخطط
|
||||
|
||||
1. **تصميم مفتاح أساسي غير فعال**
|
||||
الحالي: `PRIMARY KEY (collection, s, p, o)`.
|
||||
يؤدي إلى تجميع ضعيف لأنماط الوصول الشائعة.
|
||||
يجبر على استخدام فهرس ثانوي مكلف.
|
||||
|
||||
2. **إفراط في استخدام الفهرس الثانوي** ⚠️
|
||||
ثلاثة فهارس ثانوية على أعمدة ذات قيم عالية (s، p، o).
|
||||
الفهارس الثانوية في Cassandra مكلفة ولا تتوسع بشكل جيد.
|
||||
تتطلب الاستعلامات 6 و 7 `ALLOW FILTERING` مما يشير إلى نموذج بيانات ضعيف.
|
||||
|
||||
3. **خطر التقسيم الساخن**
|
||||
يمكن أن يؤدي مفتاح التقسيم الواحد `collection` إلى إنشاء تقسيمات ساخنة.
|
||||
ستتركز المجموعات الكبيرة على عقد فردية.
|
||||
لا توجد استراتيجية توزيع لتحقيق موازنة التحميل.
|
||||
|
||||
### مشكلات على مستوى الاستعلام
|
||||
|
||||
1. **استخدام ALLOW FILTERING** ⚠️
|
||||
يتطلب نوعان من الاستعلامات (get_po، get_os) `ALLOW FILTERING`.
|
||||
هذه الاستعلامات تفحص العديد من التقسيمات وهي مكلفة للغاية.
|
||||
يتدهور الأداء خطيًا مع حجم البيانات.
|
||||
|
||||
2. **أنماط وصول غير فعالة**
|
||||
لا توجد تحسينات لأنماط استعلام RDF الشائعة.
|
||||
فهارس مركبة مفقودة لتوليفات الاستعلامات المتكررة.
|
||||
لا توجد اعتبارات لأنماط اجتياز الرسم البياني.
|
||||
|
||||
3. **نقص في تحسين الاستعلام**
|
||||
لا يوجد تخزين مؤقت لبيانات الاستعلامات المُعدة.
|
||||
لا توجد تلميحات أو استراتيجيات لتحسين الاستعلام.
|
||||
لا توجد اعتبارات للتقسيم إلى صفحات تتجاوز LIMIT البسيطة.
|
||||
|
||||
## بيان المشكلة
|
||||
|
||||
يحتوي تطبيق قاعدة المعرفة الحالي في Cassandra على نقطتي اختناق أداء حاسمتين:
|
||||
|
||||
### 1. أداء استعلام get_po غير فعال
|
||||
|
||||
الاستعلام `get_po(collection, p, o)` غير فعال للغاية لأنه يتطلب `ALLOW FILTERING`:
|
||||
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
**لماذا هذه مشكلة:**
|
||||
`ALLOW FILTERING` تجبر Cassandra على فحص جميع الأقسام داخل المجموعة.
|
||||
تتدهور الأداء بشكل خطي مع حجم البيانات.
|
||||
هذا نمط استعلام RDF شائع (إيجاد الموضوعات التي لها علاقة محددة بين الفاعل والمفعول به).
|
||||
يؤدي ذلك إلى زيادة كبيرة في الحمل على المجموعة مع نمو البيانات.
|
||||
|
||||
### 2. استراتيجية تجميع غير فعالة
|
||||
|
||||
المفتاح الأساسي الحالي `PRIMARY KEY (collection, s, p, o)` يوفر فوائد تجميع محدودة:
|
||||
|
||||
**المشاكل المتعلقة بالتجميع الحالي:**
|
||||
`collection` كمفتاح قسم لا يوزع البيانات بشكل فعال.
|
||||
تحتوي معظم المجموعات على بيانات متنوعة مما يجعل التجميع غير فعال.
|
||||
لا توجد اعتبارات لأنماط الوصول الشائعة في استعلامات RDF.
|
||||
تخلق المجموعات الكبيرة أقسامًا "ساخنة" على عقد فردية.
|
||||
لا تعمل أعمدة التجميع (s، p، o) على تحسين أنماط اجتياز الرسم البياني النموذجية.
|
||||
|
||||
**التأثير:**
|
||||
لا تستفيد الاستعلامات من قرب البيانات.
|
||||
استخدام ضعيف لذاكرة التخزين المؤقت.
|
||||
توزيع غير متساوٍ للحمل عبر عقد المجموعة.
|
||||
اختناقات في قابلية التوسع مع نمو المجموعات.
|
||||
|
||||
## الحل المقترح: استراتيجية إلغاء التسوية باستخدام 4 جداول
|
||||
|
||||
### نظرة عامة
|
||||
|
||||
استبدل الجدول `triples` الواحد بأربعة جداول مصممة خصيصًا، كل منها مُحسَّن لأنماط استعلام محددة. هذا يلغي الحاجة إلى الفهارس الثانوية و ALLOW FILTERING مع توفير أداء مثالي لجميع أنواع الاستعلامات. يتيح الجدول الرابع حذف المجموعات بكفاءة على الرغم من مفاتيح الأقسام المركبة.
|
||||
|
||||
### تصميم المخطط الجديد
|
||||
|
||||
**الجدول 1: الاستعلامات المرتكزة على الموضوع (triples_s)**
|
||||
```sql
|
||||
CREATE TABLE triples_s (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY ((collection, s), p, o)
|
||||
);
|
||||
```
|
||||
**تحسينات:** get_s، get_sp، get_os
|
||||
**مفتاح التقسيم:** (collection, s) - توزيع أفضل من مجرد استخدام collection وحده.
|
||||
**التجميع:** (p, o) - يتيح عمليات بحث فعالة عن المحددات/الكائنات لكيان معين.
|
||||
|
||||
**الجدول 2: استعلامات المحدد-الكائن (triples_p)**
|
||||
```sql
|
||||
CREATE TABLE triples_p (
|
||||
collection text,
|
||||
p text,
|
||||
o text,
|
||||
s text,
|
||||
PRIMARY KEY ((collection, p), o, s)
|
||||
);
|
||||
```
|
||||
**تحسين:** get_p, get_po (يزيل الحاجة إلى ALLOW FILTERING!)
|
||||
**مفتاح التقسيم:** (collection, p) - وصول مباشر عبر الشرط.
|
||||
**التجميع:** (o, s) - تصفح فعال للكائنات والموضوعات.
|
||||
|
||||
**الجدول 3: الاستعلامات المرتكزة على الكائنات (triples_o)**
|
||||
```sql
|
||||
CREATE TABLE triples_o (
|
||||
collection text,
|
||||
o text,
|
||||
s text,
|
||||
p text,
|
||||
PRIMARY KEY ((collection, o), s, p)
|
||||
);
|
||||
```
|
||||
**التحسينات:** get_o
|
||||
**مفتاح التقسيم:** (collection, o) - وصول مباشر عن طريق الكائن
|
||||
**التجميع:** (s, p) - تصفح فعال للموضوع والمسند
|
||||
|
||||
**الجدول 4: إدارة المجموعات والاستعلامات SPO (triples_collection)**
|
||||
```sql
|
||||
CREATE TABLE triples_collection (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
**التحسينات:** get_spo، delete_collection
|
||||
**مفتاح التقسيم:** مجموعة فقط - يتيح عمليات فعالة على مستوى المجموعة.
|
||||
**التجميع:** (s, p, o) - ترتيب ثلاثي قياسي.
|
||||
**الغرض:** استخدام مزدوج للبحث الدقيق عن SPO وكمؤشر للحذف.
|
||||
|
||||
### تعيين الاستعلام
|
||||
|
||||
| الاستعلام الأصلي | الجدول الهدف | تحسين الأداء |
|
||||
|----------------|-------------|------------------------|
|
||||
| get_all(collection) | triples_s | السماح بالتصفية (مقبول للمسح) |
|
||||
| get_s(collection, s) | triples_s | وصول مباشر إلى التقسيم |
|
||||
| get_p(collection, p) | triples_p | وصول مباشر إلى التقسيم |
|
||||
| get_o(collection, o) | triples_o | وصول مباشر إلى التقسيم |
|
||||
| get_sp(collection, s, p) | triples_s | التقسيم + التجميع |
|
||||
| get_po(collection, p, o) | triples_p | **لا مزيد من السماح بالتصفية!** |
|
||||
| get_os(collection, o, s) | triples_o | التقسيم + التجميع |
|
||||
| get_spo(collection, s, p, o) | triples_collection | بحث مباشر عن المفتاح |
|
||||
| delete_collection(collection) | triples_collection | قراءة الفهرس، حذف مجمع |
|
||||
|
||||
### استراتيجية حذف المجموعة
|
||||
|
||||
مع مفاتيح التقسيم المركبة، لا يمكننا ببساطة تنفيذ `DELETE FROM table WHERE collection = ?`. بدلاً من ذلك:
|
||||
|
||||
1. **مرحلة القراءة:** استعلام `triples_collection` لسرد جميع الثلاثيات:
|
||||
```sql
|
||||
SELECT s, p, o FROM triples_collection WHERE collection = ?
|
||||
```
|
||||
هذا فعال لأنه `collection` هو مفتاح التقسيم لهذه الجدولة.
|
||||
|
||||
2. **مرحلة الحذف:** لكل ثلاثية (s, p, o)، قم بالحذف من جميع الجداول الأربعة باستخدام مفاتيح التقسيم الكاملة:
|
||||
```sql
|
||||
DELETE FROM triples_s WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
DELETE FROM triples_p WHERE collection = ? AND p = ? AND o = ? AND s = ?
|
||||
DELETE FROM triples_o WHERE collection = ? AND o = ? AND s = ? AND p = ?
|
||||
DELETE FROM triples_collection WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
```
|
||||
يتم تجميع البيانات في مجموعات مكونة من 100 عنصر لتحقيق الكفاءة.
|
||||
|
||||
**تحليل المقايضات:**
|
||||
✅ يحافظ على الأداء الأمثل للاستعلامات مع الأقسام الموزعة.
|
||||
✅ لا توجد أقسام "ساخنة" للمجموعات الكبيرة.
|
||||
❌ منطق حذف أكثر تعقيدًا (قراءة ثم حذف).
|
||||
❌ وقت الحذف يتناسب مع حجم المجموعة.
|
||||
|
||||
### المزايا
|
||||
|
||||
1. **يزيل الحاجة إلى ALLOW FILTERING** - كل استعلام لديه مسار وصول أمثل (باستثناء فحص get_all).
|
||||
2. **لا توجد فهارس ثانوية** - كل جدول هو الفهرس لنمط الاستعلام الخاص به.
|
||||
3. **توزيع أفضل للبيانات** - مفاتيح التقسيم المركبة توزع الحمل بشكل فعال.
|
||||
4. **أداء متوقع** - وقت الاستعلام يتناسب مع حجم النتيجة، وليس إجمالي البيانات.
|
||||
5. **يستفيد من نقاط قوة Cassandra** - مصمم ليتناسب مع بنية Cassandra.
|
||||
6. **يمكن حذف المجموعات** - تعمل triples_collection كفهرس للحذف.
|
||||
|
||||
## خطة التنفيذ
|
||||
|
||||
### الملفات التي تتطلب تغييرات
|
||||
|
||||
#### الملف الأساسي للتنفيذ
|
||||
|
||||
**`trustgraph-flow/trustgraph/direct/cassandra_kg.py`** - مطلوب إعادة كتابة كاملة.
|
||||
|
||||
**الطرق الحالية التي تتطلب إعادة هيكلة:**
|
||||
```python
|
||||
# Schema initialization
|
||||
def init(self) -> None # Replace single table with three tables
|
||||
|
||||
# Insert operations
|
||||
def insert(self, collection, s, p, o) -> None # Write to all three tables
|
||||
|
||||
# Query operations (API unchanged, implementation optimized)
|
||||
def get_all(self, collection, limit=50) # Use triples_by_subject
|
||||
def get_s(self, collection, s, limit=10) # Use triples_by_subject
|
||||
def get_p(self, collection, p, limit=10) # Use triples_by_po
|
||||
def get_o(self, collection, o, limit=10) # Use triples_by_object
|
||||
def get_sp(self, collection, s, p, limit=10) # Use triples_by_subject
|
||||
def get_po(self, collection, p, o, limit=10) # Use triples_by_po (NO ALLOW FILTERING!)
|
||||
def get_os(self, collection, o, s, limit=10) # Use triples_by_subject
|
||||
def get_spo(self, collection, s, p, o, limit=10) # Use triples_by_subject
|
||||
|
||||
# Collection management
|
||||
def delete_collection(self, collection) -> None # Delete from all three tables
|
||||
```
|
||||
|
||||
#### ملفات التكامل (لا يلزم إجراء أي تغييرات منطقية)
|
||||
|
||||
**`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`**
|
||||
لا يلزم إجراء أي تغييرات - تستخدم واجهة برمجة تطبيقات KnowledgeGraph الحالية.
|
||||
تستفيد تلقائيًا من تحسينات الأداء.
|
||||
|
||||
**`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`**
|
||||
لا يلزم إجراء أي تغييرات - تستخدم واجهة برمجة تطبيقات KnowledgeGraph الحالية.
|
||||
تستفيد تلقائيًا من تحسينات الأداء.
|
||||
|
||||
### ملفات الاختبار التي تتطلب تحديثات
|
||||
|
||||
#### اختبارات الوحدة
|
||||
**`tests/unit/test_storage/test_triples_cassandra_storage.py`**
|
||||
تحديث توقعات الاختبار للتغييرات في المخطط.
|
||||
إضافة اختبارات لضمان الاتساق بين الجداول المتعددة.
|
||||
التحقق من عدم وجود ALLOW FILTERING في خطط الاستعلام.
|
||||
|
||||
**`tests/unit/test_query/test_triples_cassandra_query.py`**
|
||||
تحديث التأكيدات المتعلقة بالأداء.
|
||||
اختبار جميع أنماط الاستعلام الثمانية مقابل الجداول الجديدة.
|
||||
التحقق من توجيه الاستعلام إلى الجداول الصحيحة.
|
||||
|
||||
#### اختبارات التكامل
|
||||
**`tests/integration/test_cassandra_integration.py`**
|
||||
اختبار شامل مع المخطط الجديد.
|
||||
مقارنات قياس الأداء.
|
||||
التحقق من اتساق البيانات عبر الجداول.
|
||||
|
||||
**`tests/unit/test_storage/test_cassandra_config_integration.py`**
|
||||
تحديث اختبارات التحقق من صحة المخطط.
|
||||
اختبار سيناريوهات الترحيل.
|
||||
|
||||
### استراتيجية التنفيذ
|
||||
|
||||
#### المرحلة الأولى: المخطط والطرق الأساسية
|
||||
1. **إعادة كتابة الطريقة `init()`** - إنشاء أربعة جداول بدلاً من جدول واحد.
|
||||
2. **إعادة كتابة الطريقة `insert()`** - عمليات كتابة مجمعة إلى جميع الجداول الأربعة.
|
||||
3. **تنفيذ عبارات مُعدة** - للحصول على أداء مثالي.
|
||||
4. **إضافة منطق توجيه الجدول** - لتوجيه الاستعلامات إلى الجداول المثلى.
|
||||
5. **تنفيذ حذف المجموعة** - القراءة من triples_collection، وحذف مجمع من جميع الجداول.
|
||||
|
||||
#### المرحلة الثانية: تحسين طريقة الاستعلام
|
||||
1. **إعادة كتابة كل طريقة get_*** لاستخدام الجدول الأمثل.
|
||||
2. **إزالة جميع استخدامات ALLOW FILTERING**.
|
||||
3. **تنفيذ استخدام فعال لمفتاح التجميع**.
|
||||
4. **إضافة تسجيل أداء الاستعلام**.
|
||||
|
||||
#### المرحلة الثالثة: إدارة المجموعة
|
||||
1. **تحديث `delete_collection()`** - إزالتها من جميع الجداول الثلاثة.
|
||||
2. **إضافة التحقق من الاتساق** - لضمان بقاء جميع الجداول متزامنة.
|
||||
3. **تنفيذ عمليات مجمعة** - لعمليات متعددة الجداول ذرية.
|
||||
|
||||
### تفاصيل التنفيذ الرئيسية
|
||||
|
||||
#### استراتيجية الكتابة المجمعة
|
||||
```python
|
||||
def insert(self, collection, s, p, o):
|
||||
batch = BatchStatement()
|
||||
|
||||
# Insert into all four tables
|
||||
batch.add(self.insert_subject_stmt, (collection, s, p, o))
|
||||
batch.add(self.insert_po_stmt, (collection, p, o, s))
|
||||
batch.add(self.insert_object_stmt, (collection, o, s, p))
|
||||
batch.add(self.insert_collection_stmt, (collection, s, p, o))
|
||||
|
||||
self.session.execute(batch)
|
||||
```
|
||||
|
||||
#### منطق توجيه الاستعلامات
|
||||
```python
|
||||
def get_po(self, collection, p, o, limit=10):
|
||||
# Route to triples_p table - NO ALLOW FILTERING!
|
||||
return self.session.execute(
|
||||
self.get_po_stmt,
|
||||
(collection, p, o, limit)
|
||||
)
|
||||
|
||||
def get_spo(self, collection, s, p, o, limit=10):
|
||||
# Route to triples_collection table for exact SPO lookup
|
||||
return self.session.execute(
|
||||
self.get_spo_stmt,
|
||||
(collection, s, p, o, limit)
|
||||
)
|
||||
```
|
||||
|
||||
#### منطق حذف المجموعة
|
||||
```python
|
||||
def delete_collection(self, collection):
|
||||
# Step 1: Read all triples from collection table
|
||||
rows = self.session.execute(
|
||||
f"SELECT s, p, o FROM {self.collection_table} WHERE collection = %s",
|
||||
(collection,)
|
||||
)
|
||||
|
||||
# Step 2: Batch delete from all 4 tables
|
||||
batch = BatchStatement()
|
||||
count = 0
|
||||
|
||||
for row in rows:
|
||||
s, p, o = row.s, row.p, row.o
|
||||
|
||||
# Delete using full partition keys for each table
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.subject_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.po_table} WHERE collection = ? AND p = ? AND o = ? AND s = ?"
|
||||
), (collection, p, o, s))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.object_table} WHERE collection = ? AND o = ? AND s = ? AND p = ?"
|
||||
), (collection, o, s, p))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.collection_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
count += 1
|
||||
|
||||
# Execute every 100 triples to avoid oversized batches
|
||||
if count % 100 == 0:
|
||||
self.session.execute(batch)
|
||||
batch = BatchStatement()
|
||||
|
||||
# Execute remaining deletions
|
||||
if count % 100 != 0:
|
||||
self.session.execute(batch)
|
||||
|
||||
logger.info(f"Deleted {count} triples from collection {collection}")
|
||||
```
|
||||
|
||||
### تحسين عبارات SQL المُعدة (Prepared Statements)
|
||||
```python
|
||||
def prepare_statements(self):
|
||||
# Cache prepared statements for better performance
|
||||
self.insert_subject_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.subject_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_po_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.po_table} (collection, p, o, s) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_object_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.object_table} (collection, o, s, p) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_collection_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.collection_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
# ... query statements
|
||||
```
|
||||
|
||||
## استراتيجية الترحيل
|
||||
|
||||
### نهج ترحيل البيانات
|
||||
|
||||
#### الخيار الأول: النشر الأزرق-الأخضر (موصى به)
|
||||
1. **نشر المخطط الجديد جنبًا إلى جنب مع المخطط الحالي** - استخدم أسماء جداول مختلفة مؤقتًا.
|
||||
2. **فترة الكتابة المزدوجة** - الكتابة إلى كل من المخططين القديم والجديد خلال فترة الانتقال.
|
||||
3. **ترحيل البيانات في الخلفية** - نسخ البيانات الموجودة إلى الجداول الجديدة.
|
||||
4. **توجيه عمليات القراءة** - توجيه الاستعلامات إلى الجداول الجديدة بمجرد ترحيل البيانات.
|
||||
5. **إزالة الجداول القديمة** - بعد فترة التحقق.
|
||||
|
||||
#### الخيار الثاني: الترحيل في المكان
|
||||
1. **إضافة المخطط** - إنشاء جداول جديدة في مساحة المفاتيح الحالية.
|
||||
2. **برنامج ترحيل البيانات** - نسخ دفعي من الجدول القديم إلى الجداول الجديدة.
|
||||
3. **تحديث التطبيق** - نشر التعليمات البرمجية الجديدة بعد اكتمال الترحيل.
|
||||
4. **تنظيف الجدول القديم** - إزالة الجدول القديم والفهارس.
|
||||
|
||||
### التوافق مع الإصدارات السابقة
|
||||
|
||||
#### استراتيجية النشر
|
||||
```python
|
||||
# Environment variable to control table usage during migration
|
||||
USE_LEGACY_TABLES = os.getenv('CASSANDRA_USE_LEGACY', 'false').lower() == 'true'
|
||||
|
||||
class KnowledgeGraph:
|
||||
def __init__(self, ...):
|
||||
if USE_LEGACY_TABLES:
|
||||
self.init_legacy_schema()
|
||||
else:
|
||||
self.init_optimized_schema()
|
||||
```
|
||||
|
||||
#### نص ترحيل
|
||||
```python
|
||||
def migrate_data():
|
||||
# Read from old table
|
||||
old_triples = session.execute("SELECT collection, s, p, o FROM triples")
|
||||
|
||||
# Batch write to new tables
|
||||
for batch in batched(old_triples, 100):
|
||||
batch_stmt = BatchStatement()
|
||||
for row in batch:
|
||||
# Add to all three new tables
|
||||
batch_stmt.add(insert_subject_stmt, row)
|
||||
batch_stmt.add(insert_po_stmt, (row.collection, row.p, row.o, row.s))
|
||||
batch_stmt.add(insert_object_stmt, (row.collection, row.o, row.s, row.p))
|
||||
session.execute(batch_stmt)
|
||||
```
|
||||
|
||||
### استراتيجية التحقق من الصحة
|
||||
|
||||
#### فحوصات تناسق البيانات
|
||||
```python
|
||||
def validate_migration():
|
||||
# Count total records in old vs new tables
|
||||
old_count = session.execute("SELECT COUNT(*) FROM triples WHERE collection = ?", (collection,))
|
||||
new_count = session.execute("SELECT COUNT(*) FROM triples_by_subject WHERE collection = ?", (collection,))
|
||||
|
||||
assert old_count == new_count, f"Record count mismatch: {old_count} vs {new_count}"
|
||||
|
||||
# Spot check random samples
|
||||
sample_queries = generate_test_queries()
|
||||
for query in sample_queries:
|
||||
old_result = execute_legacy_query(query)
|
||||
new_result = execute_optimized_query(query)
|
||||
assert old_result == new_result, f"Query results differ for {query}"
|
||||
```
|
||||
|
||||
## استراتيجية الاختبار
|
||||
|
||||
### اختبار الأداء
|
||||
|
||||
#### سيناريوهات قياس الأداء
|
||||
1. **مقارنة أداء الاستعلامات**
|
||||
مقاييس الأداء قبل وبعد لجميع أنواع الاستعلامات الثمانية.
|
||||
التركيز على تحسين أداء `get_po` (إزالة `ALLOW FILTERING`).
|
||||
قياس زمن استجابة الاستعلامات تحت أحجام بيانات مختلفة.
|
||||
|
||||
2. **اختبار التحميل**
|
||||
تنفيذ استعلامات متزامنة.
|
||||
معدل نقل البيانات مع العمليات الدفعية.
|
||||
استخدام الذاكرة ووحدة المعالجة المركزية.
|
||||
|
||||
3. **اختبار قابلية التوسع**
|
||||
الأداء مع زيادة أحجام المجموعات.
|
||||
توزيع الاستعلامات عبر مجموعات متعددة.
|
||||
استخدام عقد المجموعة.
|
||||
|
||||
#### مجموعات بيانات الاختبار
|
||||
**صغيرة:** 10 آلاف ثلاثية لكل مجموعة.
|
||||
**متوسطة:** 100 ألف ثلاثية لكل مجموعة.
|
||||
**كبيرة:** أكثر من مليون ثلاثية لكل مجموعة.
|
||||
**مجموعات متعددة:** اختبار توزيع التقسيم.
|
||||
|
||||
### اختبار وظيفي
|
||||
|
||||
#### تحديثات اختبار الوحدات
|
||||
```python
|
||||
# Example test structure for new implementation
|
||||
class TestCassandraKGPerformance:
|
||||
def test_get_po_no_allow_filtering(self):
|
||||
# Verify get_po queries don't use ALLOW FILTERING
|
||||
with patch('cassandra.cluster.Session.execute') as mock_execute:
|
||||
kg.get_po('test_collection', 'predicate', 'object')
|
||||
executed_query = mock_execute.call_args[0][0]
|
||||
assert 'ALLOW FILTERING' not in executed_query
|
||||
|
||||
def test_multi_table_consistency(self):
|
||||
# Verify all tables stay in sync
|
||||
kg.insert('test', 's1', 'p1', 'o1')
|
||||
|
||||
# Check all tables contain the triple
|
||||
assert_triple_exists('triples_by_subject', 'test', 's1', 'p1', 'o1')
|
||||
assert_triple_exists('triples_by_po', 'test', 'p1', 'o1', 's1')
|
||||
assert_triple_exists('triples_by_object', 'test', 'o1', 's1', 'p1')
|
||||
```
|
||||
|
||||
#### تحديثات اختبار التكامل
|
||||
```python
|
||||
class TestCassandraIntegration:
|
||||
def test_query_performance_regression(self):
|
||||
# Ensure new implementation is faster than old
|
||||
old_time = benchmark_legacy_get_po()
|
||||
new_time = benchmark_optimized_get_po()
|
||||
assert new_time < old_time * 0.5 # At least 50% improvement
|
||||
|
||||
def test_end_to_end_workflow(self):
|
||||
# Test complete write -> query -> delete cycle
|
||||
# Verify no performance degradation in integration
|
||||
```
|
||||
|
||||
### خطة التراجع
|
||||
|
||||
#### استراتيجية تراجع سريعة
|
||||
1. **تبديل متغيرات البيئة** - العودة إلى الجداول القديمة على الفور.
|
||||
2. **الاحتفاظ بالجداول القديمة** - لا تقم بإزالتها حتى يتم إثبات الأداء.
|
||||
3. **تنبيهات المراقبة** - تشغيل تلقائي للتراجع بناءً على معدلات الخطأ/زمن الاستجابة.
|
||||
|
||||
#### التحقق من التراجع
|
||||
```python
|
||||
def rollback_to_legacy():
|
||||
# Set environment variable
|
||||
os.environ['CASSANDRA_USE_LEGACY'] = 'true'
|
||||
|
||||
# Restart services to pick up change
|
||||
restart_cassandra_services()
|
||||
|
||||
# Validate functionality
|
||||
run_smoke_tests()
|
||||
```
|
||||
|
||||
## المخاطر والاعتبارات
|
||||
|
||||
### مخاطر الأداء
|
||||
**زيادة زمن الاستجابة للكتابة** - 4 عمليات كتابة لكل عملية إدخال (أكثر بنسبة 33٪ من مقاربة الجدول الثلاثي)
|
||||
**العبء التخزيني** - 4 أضعاف متطلبات التخزين (أكثر بنسبة 33٪ من مقاربة الجدول الثلاثي)
|
||||
**فشل عمليات الكتابة المجمعة** - الحاجة إلى معالجة الأخطاء بشكل صحيح
|
||||
**تعقيد الحذف** - يتطلب حذف المجموعة حلقة قراءة ثم حذف
|
||||
|
||||
### المخاطر التشغيلية
|
||||
**تعقيد الترحيل** - ترحيل البيانات لمجموعات البيانات الكبيرة
|
||||
**تحديات الاتساق** - ضمان بقاء جميع الجداول متزامنة
|
||||
**فجوات المراقبة** - الحاجة إلى مقاييس جديدة لعمليات الجداول المتعددة
|
||||
|
||||
### استراتيجيات التخفيف
|
||||
1. **النشر التدريجي** - ابدأ بمجموعات صغيرة
|
||||
2. **مراقبة شاملة** - تتبع جميع مقاييس الأداء
|
||||
3. **التحقق الآلي** - فحص الاتساق المستمر
|
||||
4. **إمكانية التراجع السريع** - اختيار الجدول بناءً على البيئة
|
||||
|
||||
## معايير النجاح
|
||||
|
||||
### تحسينات الأداء
|
||||
[ ] **إزالة ALLOW FILTERING** - تعمل الاستعلامات get_po و get_os بدون تصفية
|
||||
[ ] **تقليل زمن استجابة الاستعلام** - تحسن بنسبة 50٪ أو أكثر في أوقات استجابة الاستعلام
|
||||
[ ] **توزيع أفضل للعبء** - لا توجد أقسام "ساخنة"، وتوزيع متساوٍ عبر عقد المجموعة
|
||||
[ ] **أداء قابل للتوسع** - وقت الاستعلام يتناسب مع حجم النتيجة، وليس إجمالي البيانات
|
||||
|
||||
### المتطلبات الوظيفية
|
||||
[ ] **توافق واجهة برمجة التطبيقات (API)** - يستمر جميع التعليمات البرمجية الحالية في العمل دون تغيير
|
||||
[ ] **اتساق البيانات** - تظل جميع الجداول الثلاثة متزامنة
|
||||
[ ] **عدم فقدان البيانات** - يحافظ الترحيل على جميع الثلاثيات الموجودة
|
||||
[ ] **التوافق مع الإصدارات السابقة** - القدرة على العودة إلى المخطط القديم
|
||||
|
||||
### المتطلبات التشغيلية
|
||||
[ ] **ترحيل آمن** - نشر أخضر/أزرق مع إمكانية التراجع
|
||||
[ ] **تغطية المراقبة** - مقاييس شاملة لعمليات الجداول المتعددة
|
||||
[ ] **تغطية الاختبار** - تم اختبار جميع أنماط الاستعلام باستخدام معايير الأداء
|
||||
[ ] **التوثيق** - تحديث إجراءات النشر والتشغيل
|
||||
|
||||
## الجدول الزمني
|
||||
|
||||
### المرحلة 1: التنفيذ
|
||||
[ ] إعادة كتابة `cassandra_kg.py` باستخدام مخطط الجداول المتعددة
|
||||
[ ] تنفيذ عمليات الكتابة المجمعة
|
||||
[ ] إضافة تحسينات باستخدام عبارات مُعدة
|
||||
[ ] تحديث اختبارات الوحدة
|
||||
|
||||
### المرحلة 2: اختبار التكامل
|
||||
[ ] تحديث اختبارات التكامل
|
||||
[ ] قياس الأداء
|
||||
[ ] اختبار التحميل باستخدام أحجام بيانات واقعية
|
||||
[ ] نصوص التحقق من اتساق البيانات
|
||||
|
||||
### المرحلة 3: تخطيط الترحيل
|
||||
[ ] نصوص النشر الأخضر/الأزرق
|
||||
[ ] أدوات ترحيل البيانات
|
||||
[ ] تحديثات لوحة معلومات المراقبة
|
||||
[ ] إجراءات التراجع
|
||||
|
||||
### المرحلة 4: النشر في بيئة الإنتاج
|
||||
[ ] النشر التدريجي في بيئة الإنتاج
|
||||
[ ] مراقبة الأداء والتحقق من صحته
|
||||
[ ] تنظيف الجداول القديمة
|
||||
[ ] تحديثات التوثيق
|
||||
|
||||
## الخلاصة
|
||||
|
||||
تعالج هذه الاستراتيجية لإلغاء التسوية متعددة الجداول بشكل مباشر عنقودين رئيسيين للأداء:
|
||||
|
||||
1. **تقضي على ALLOW FILTERING المكلفة** من خلال توفير هياكل جداول مثالية لكل نمط استعلام
|
||||
2. **تحسين فعالية التجميع** من خلال مفاتيح التقسيم المركبة التي توزع الحمل بشكل صحيح
|
||||
|
||||
تستفيد هذه الطريقة من نقاط قوة Cassandra مع الحفاظ على توافق كامل مع واجهة برمجة التطبيقات (API)، مما يضمن أن التعليمات البرمجية الحالية تستفيد تلقائيًا من تحسينات الأداء.
|
||||
687
docs/tech-specs/cassandra-performance-refactor.es.md
Normal file
687
docs/tech-specs/cassandra-performance-refactor.es.md
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificación Técnica: Refactorización del Rendimiento de la Base de Conocimiento Cassandra"
|
||||
parent: "Spanish (Beta)"
|
||||
---
|
||||
|
||||
# Especificación Técnica: Refactorización del Rendimiento de la Base de Conocimiento Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**Estado:** Borrador
|
||||
**Autor:** Asistente
|
||||
**Fecha:** 2025-09-18
|
||||
|
||||
## Resumen
|
||||
|
||||
Esta especificación aborda los problemas de rendimiento en la implementación de la base de conocimiento TrustGraph Cassandra y propone optimizaciones para el almacenamiento y la consulta de triples RDF.
|
||||
|
||||
## Implementación Actual
|
||||
|
||||
### Diseño del Esquema
|
||||
|
||||
La implementación actual utiliza un diseño de tabla única en `trustgraph-flow/trustgraph/direct/cassandra_kg.py`:
|
||||
|
||||
```sql
|
||||
CREATE TABLE triples (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
|
||||
**Índices Secundarios:**
|
||||
`triples_s` EN `s` (sujeto)
|
||||
`triples_p` EN `p` (predicado)
|
||||
`triples_o` EN `o` (objeto)
|
||||
|
||||
### Patrones de Consulta
|
||||
|
||||
La implementación actual admite 8 patrones de consulta distintos:
|
||||
|
||||
1. **get_all(colección, límite=50)** - Recupera todas las triples para una colección
|
||||
```sql
|
||||
SELECT s, p, o FROM triples WHERE collection = ? LIMIT 50
|
||||
```
|
||||
|
||||
2. **get_s(colección, s, límite=10)** - Consulta por tema.
|
||||
```sql
|
||||
SELECT p, o FROM triples WHERE collection = ? AND s = ? LIMIT 10
|
||||
```
|
||||
|
||||
3. **get_p(colección, p, límite=10)** - Consulta por predicado
|
||||
```sql
|
||||
SELECT s, o FROM triples WHERE collection = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
4. **get_o(colección, o, límite=10)** - Consulta por objeto
|
||||
```sql
|
||||
SELECT s, p FROM triples WHERE collection = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
5. **get_sp(colección, s, p, limit=10)** - Consulta por sujeto + predicado
|
||||
```sql
|
||||
SELECT o FROM triples WHERE collection = ? AND s = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
6. **get_po(collection, p, o, limit=10)** - Consulta por predicado + objeto ⚠️
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
7. **get_os(collection, o, s, limit=10)** - Consulta por objeto + sujeto ⚠️
|
||||
```sql
|
||||
SELECT p FROM triples WHERE collection = ? AND o = ? AND s = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
8. **get_spo(colección, s, p, o, límite=10)** - Coincidencia exacta de tripleta.
|
||||
```sql
|
||||
SELECT s as x FROM triples WHERE collection = ? AND s = ? AND p = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
### Arquitectura Actual
|
||||
|
||||
**Archivo: `trustgraph-flow/trustgraph/direct/cassandra_kg.py`**
|
||||
Clase única `KnowledgeGraph` que gestiona todas las operaciones
|
||||
Agrupación de conexiones a través de una lista global `_active_clusters`
|
||||
Nombre de tabla fijo: `"triples"`
|
||||
Espacio de claves por modelo de usuario
|
||||
Replicación SimpleStrategy con factor 1
|
||||
|
||||
**Puntos de Integración:**
|
||||
**Ruta de Escritura:** `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
**Ruta de Consulta:** `trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
**Almacén de Conocimiento:** `trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
|
||||
## Problemas de Rendimiento Identificados
|
||||
|
||||
### Problemas a Nivel de Esquema
|
||||
|
||||
1. **Diseño de Clave Primaria Ineficiente**
|
||||
Actual: `PRIMARY KEY (collection, s, p, o)`
|
||||
Resulta en un agrupamiento deficiente para patrones de acceso comunes
|
||||
Obliga al uso de índices secundarios costosos
|
||||
|
||||
2. **Uso Excesivo de Índices Secundarios** ⚠️
|
||||
Tres índices secundarios en columnas de alta cardinalidad (s, p, o)
|
||||
Los índices secundarios en Cassandra son costosos y no escalan bien
|
||||
Las consultas 6 y 7 requieren `ALLOW FILTERING`, lo que indica un modelado de datos deficiente
|
||||
|
||||
3. **Riesgo de Particiones Calientes**
|
||||
Una única clave de partición `collection` puede crear particiones calientes
|
||||
Las colecciones grandes se concentrarán en nodos individuales
|
||||
No hay estrategia de distribución para el equilibrio de carga
|
||||
|
||||
### Problemas a Nivel de Consulta
|
||||
|
||||
1. **Uso de ALLOW FILTERING** ⚠️
|
||||
Dos tipos de consulta (get_po, get_os) requieren `ALLOW FILTERING`
|
||||
Estas consultas escanean múltiples particiones y son extremadamente costosas
|
||||
El rendimiento disminuye linealmente con el tamaño de los datos
|
||||
|
||||
2. **Patrones de Acceso Ineficientes**
|
||||
No hay optimización para patrones de consulta RDF comunes
|
||||
Faltan índices compuestos para combinaciones de consulta frecuentes
|
||||
No se tiene en cuenta los patrones de recorrido de grafos
|
||||
|
||||
3. **Falta de Optimización de Consultas**
|
||||
No hay almacenamiento en caché de sentencias preparadas
|
||||
No hay sugerencias de consulta ni estrategias de optimización
|
||||
No se tiene en cuenta la paginación más allá de un simple LIMIT
|
||||
|
||||
## Declaración del Problema
|
||||
|
||||
La implementación actual de la base de conocimiento de Cassandra tiene dos cuellos de botella críticos de rendimiento:
|
||||
|
||||
### 1. Rendimiento Ineficiente de la Consulta get_po
|
||||
|
||||
La consulta `get_po(collection, p, o)` es extremadamente ineficiente debido a que requiere `ALLOW FILTERING`:
|
||||
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
**¿Por qué esto es problemático:**
|
||||
`ALLOW FILTERING` obliga a Cassandra a escanear todas las particiones dentro de la colección.
|
||||
El rendimiento disminuye linealmente con el tamaño de los datos.
|
||||
Este es un patrón de consulta RDF común (encontrar sujetos que tengan una relación específica de predicado-objeto).
|
||||
Crea una carga significativa en el clúster a medida que los datos crecen.
|
||||
|
||||
### 2. Estrategia de Clustering Deficiente
|
||||
|
||||
La clave primaria actual `PRIMARY KEY (collection, s, p, o)` proporciona beneficios de clustering mínimos:
|
||||
|
||||
**Problemas con el clustering actual:**
|
||||
`collection` como clave de partición no distribuye los datos de manera efectiva.
|
||||
La mayoría de las colecciones contienen datos diversos, lo que hace que el clustering sea ineficaz.
|
||||
No se tiene en cuenta los patrones de acceso comunes en las consultas RDF.
|
||||
Las colecciones grandes crean particiones "calientes" en nodos individuales.
|
||||
Las columnas de clustering (s, p, o) no optimizan para los patrones típicos de recorrido de grafos.
|
||||
|
||||
**Impacto:**
|
||||
Las consultas no se benefician de la localidad de los datos.
|
||||
Utilización deficiente de la caché.
|
||||
Distribución desigual de la carga en los nodos del clúster.
|
||||
Cuellos de botella de escalabilidad a medida que las colecciones crecen.
|
||||
|
||||
## Solución Propuesta: Estrategia de Desnormalización de 4 Tablas
|
||||
|
||||
### Resumen
|
||||
|
||||
Reemplace la única tabla `triples` con cuatro tablas diseñadas específicamente, cada una optimizada para patrones de consulta específicos. Esto elimina la necesidad de índices secundarios y ALLOW FILTERING, al tiempo que proporciona un rendimiento óptimo para todos los tipos de consulta. La cuarta tabla permite una eliminación eficiente de colecciones a pesar de las claves de partición compuestas.
|
||||
|
||||
### Nuevo Diseño de Esquema
|
||||
|
||||
**Tabla 1: Consultas Centradas en el Sujeto (triples_s)**
|
||||
```sql
|
||||
CREATE TABLE triples_s (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY ((collection, s), p, o)
|
||||
);
|
||||
```
|
||||
**Optimiza:** get_s, get_sp, get_os
|
||||
**Clave de partición:** (colección, s) - Mejor distribución que solo la colección.
|
||||
**Agrupamiento:** (p, o) - Permite búsquedas eficientes de predicados/objetos para un sujeto.
|
||||
|
||||
**Tabla 2: Consultas Predicado-Objeto (triples_p)**
|
||||
```sql
|
||||
CREATE TABLE triples_p (
|
||||
collection text,
|
||||
p text,
|
||||
o text,
|
||||
s text,
|
||||
PRIMARY KEY ((collection, p), o, s)
|
||||
);
|
||||
```
|
||||
**Optimiza:** get_p, get_po (¡elimina ALLOW FILTERING!)
|
||||
**Clave de partición:** (colección, p) - Acceso directo mediante predicado
|
||||
**Agrupamiento:** (o, s) - Recorrido eficiente de objeto a sujeto
|
||||
|
||||
**Tabla 3: Consultas centradas en objetos (triples_o)**
|
||||
```sql
|
||||
CREATE TABLE triples_o (
|
||||
collection text,
|
||||
o text,
|
||||
s text,
|
||||
p text,
|
||||
PRIMARY KEY ((collection, o), s, p)
|
||||
);
|
||||
```
|
||||
**Optimiza:** get_o
|
||||
**Clave de partición:** (colección, o) - Acceso directo por objeto
|
||||
**Clustering:** (s, p) - Recorrido eficiente de sujeto-predicado
|
||||
|
||||
**Tabla 4: Gestión de colecciones y consultas SPO (triples_collection)**
|
||||
```sql
|
||||
CREATE TABLE triples_collection (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
**Optimiza:** get_spo, delete_collection
|
||||
**Clave de partición:** solo colección - Permite operaciones eficientes a nivel de colección.
|
||||
**Clustering:** (s, p, o) - Orden estándar de tripletas.
|
||||
**Propósito:** Uso dual para búsquedas exactas de SPO y como índice de eliminación.
|
||||
|
||||
### Mapeo de consultas
|
||||
|
||||
| Consulta original | Tabla de destino | Mejora de rendimiento |
|
||||
|----------------|-------------|------------------------|
|
||||
| get_all(collection) | triples_s | PERMITE FILTRADO (aceptable para escaneo) |
|
||||
| get_s(collection, s) | triples_s | Acceso directo a la partición |
|
||||
| get_p(collection, p) | triples_p | Acceso directo a la partición |
|
||||
| get_o(collection, o) | triples_o | Acceso directo a la partición |
|
||||
| get_sp(collection, s, p) | triples_s | Partición + clustering |
|
||||
| get_po(collection, p, o) | triples_p | **¡Ya no se permite ALLOW FILTERING!** |
|
||||
| get_os(collection, o, s) | triples_o | Partición + clustering |
|
||||
| get_spo(collection, s, p, o) | triples_collection | Búsqueda exacta de clave |
|
||||
| delete_collection(collection) | triples_collection | Lee el índice, eliminación por lotes de todos |
|
||||
|
||||
### Estrategia de eliminación de colecciones
|
||||
|
||||
Con claves de partición compuestas, no podemos simplemente ejecutar `DELETE FROM table WHERE collection = ?`. En cambio:
|
||||
|
||||
1. **Fase de lectura:** Consulta `triples_collection` para enumerar todas las tripletas:
|
||||
```sql
|
||||
SELECT s, p, o FROM triples_collection WHERE collection = ?
|
||||
```
|
||||
Esto es eficiente ya que `collection` es la clave de partición para esta tabla.
|
||||
|
||||
2. **Fase de eliminación:** Para cada triple (s, p, o), elimine de las 4 tablas utilizando claves de partición completas:
|
||||
```sql
|
||||
DELETE FROM triples_s WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
DELETE FROM triples_p WHERE collection = ? AND p = ? AND o = ? AND s = ?
|
||||
DELETE FROM triples_o WHERE collection = ? AND o = ? AND s = ? AND p = ?
|
||||
DELETE FROM triples_collection WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
```
|
||||
Agrupado en lotes de 100 para mayor eficiencia.
|
||||
|
||||
**Análisis de compensaciones:**
|
||||
✅ Mantiene un rendimiento óptimo de las consultas con particiones distribuidas.
|
||||
✅ No hay particiones con alta carga para colecciones grandes.
|
||||
❌ Lógica de eliminación más compleja (leer y luego eliminar).
|
||||
❌ Tiempo de eliminación proporcional al tamaño de la colección.
|
||||
|
||||
### Beneficios
|
||||
|
||||
1. **Elimina ALLOW FILTERING** - Cada consulta tiene una ruta de acceso óptima (excepto el escaneo get_all).
|
||||
2. **No se requieren índices secundarios** - Cada tabla ES el índice para su patrón de consulta.
|
||||
3. **Mejor distribución de datos** - Las claves de partición compuestas distribuyen la carga de manera efectiva.
|
||||
4. **Rendimiento predecible** - El tiempo de consulta es proporcional al tamaño del resultado, no a los datos totales.
|
||||
5. **Aprovecha las fortalezas de Cassandra** - Diseñado para la arquitectura de Cassandra.
|
||||
6. **Permite la eliminación de colecciones** - triples_collection sirve como índice de eliminación.
|
||||
|
||||
## Plan de implementación
|
||||
|
||||
### Archivos que requieren cambios
|
||||
|
||||
#### Archivo de implementación principal
|
||||
|
||||
**`trustgraph-flow/trustgraph/direct/cassandra_kg.py`** - Se requiere una reescritura completa.
|
||||
|
||||
**Métodos actuales a refactorizar:**
|
||||
```python
|
||||
# Schema initialization
|
||||
def init(self) -> None # Replace single table with three tables
|
||||
|
||||
# Insert operations
|
||||
def insert(self, collection, s, p, o) -> None # Write to all three tables
|
||||
|
||||
# Query operations (API unchanged, implementation optimized)
|
||||
def get_all(self, collection, limit=50) # Use triples_by_subject
|
||||
def get_s(self, collection, s, limit=10) # Use triples_by_subject
|
||||
def get_p(self, collection, p, limit=10) # Use triples_by_po
|
||||
def get_o(self, collection, o, limit=10) # Use triples_by_object
|
||||
def get_sp(self, collection, s, p, limit=10) # Use triples_by_subject
|
||||
def get_po(self, collection, p, o, limit=10) # Use triples_by_po (NO ALLOW FILTERING!)
|
||||
def get_os(self, collection, o, s, limit=10) # Use triples_by_subject
|
||||
def get_spo(self, collection, s, p, o, limit=10) # Use triples_by_subject
|
||||
|
||||
# Collection management
|
||||
def delete_collection(self, collection) -> None # Delete from all three tables
|
||||
```
|
||||
|
||||
#### Archivos de Integración (No se requieren cambios en la lógica)
|
||||
|
||||
**`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`**
|
||||
No se necesitan cambios: utiliza la API KnowledgeGraph existente.
|
||||
Se beneficia automáticamente de las mejoras de rendimiento.
|
||||
|
||||
**`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`**
|
||||
No se necesitan cambios: utiliza la API KnowledgeGraph existente.
|
||||
Se beneficia automáticamente de las mejoras de rendimiento.
|
||||
|
||||
### Archivos de Prueba que Requieren Actualizaciones
|
||||
|
||||
#### Pruebas Unitarias
|
||||
**`tests/unit/test_storage/test_triples_cassandra_storage.py`**
|
||||
Actualizar las expectativas de las pruebas para los cambios en el esquema.
|
||||
Agregar pruebas para la consistencia de múltiples tablas.
|
||||
Verificar que no haya "ALLOW FILTERING" en los planes de consulta.
|
||||
|
||||
**`tests/unit/test_query/test_triples_cassandra_query.py`**
|
||||
Actualizar las aserciones de rendimiento.
|
||||
Probar los 8 patrones de consulta contra las nuevas tablas.
|
||||
Verificar el enrutamiento de consultas a las tablas correctas.
|
||||
|
||||
#### Pruebas de Integración
|
||||
**`tests/integration/test_cassandra_integration.py`**
|
||||
Pruebas de extremo a extremo con el nuevo esquema.
|
||||
Comparaciones de referencia de rendimiento.
|
||||
Verificación de la consistencia de los datos en todas las tablas.
|
||||
|
||||
**`tests/unit/test_storage/test_cassandra_config_integration.py`**
|
||||
Actualizar las pruebas de validación de esquema.
|
||||
Probar escenarios de migración.
|
||||
|
||||
### Estrategia de Implementación
|
||||
|
||||
#### Fase 1: Esquema y Métodos Centrales
|
||||
1. **Reescribir el método `init()`** - Crear cuatro tablas en lugar de una.
|
||||
2. **Reescribir el método `insert()`** - Escrituras por lotes a las cuatro tablas.
|
||||
3. **Implementar sentencias preparadas** - Para un rendimiento óptimo.
|
||||
4. **Agregar lógica de enrutamiento de tablas** - Dirigir las consultas a las tablas óptimas.
|
||||
5. **Implementar la eliminación de colecciones** - Leer de triples_collection, eliminar por lotes de todas las tablas.
|
||||
|
||||
#### Fase 2: Optimización de Métodos de Consulta
|
||||
1. **Reescribir cada método get_*** para usar la tabla óptima.
|
||||
2. **Eliminar todo el uso de ALLOW FILTERING**.
|
||||
3. **Implementar el uso eficiente de la clave de clustering**.
|
||||
4. **Agregar registro del rendimiento de las consultas**.
|
||||
|
||||
#### Fase 3: Gestión de Colecciones
|
||||
1. **Actualizar `delete_collection()`** - Eliminar de las tres tablas.
|
||||
2. **Agregar verificación de consistencia** - Asegurar que todas las tablas se mantengan sincronizadas.
|
||||
3. **Implementar operaciones por lotes** - Para operaciones multi-tabla atómicas.
|
||||
|
||||
### Detalles Clave de la Implementación
|
||||
|
||||
#### Estrategia de Escritura por Lotes
|
||||
```python
|
||||
def insert(self, collection, s, p, o):
|
||||
batch = BatchStatement()
|
||||
|
||||
# Insert into all four tables
|
||||
batch.add(self.insert_subject_stmt, (collection, s, p, o))
|
||||
batch.add(self.insert_po_stmt, (collection, p, o, s))
|
||||
batch.add(self.insert_object_stmt, (collection, o, s, p))
|
||||
batch.add(self.insert_collection_stmt, (collection, s, p, o))
|
||||
|
||||
self.session.execute(batch)
|
||||
```
|
||||
|
||||
#### Lógica de enrutamiento de consultas
|
||||
```python
|
||||
def get_po(self, collection, p, o, limit=10):
|
||||
# Route to triples_p table - NO ALLOW FILTERING!
|
||||
return self.session.execute(
|
||||
self.get_po_stmt,
|
||||
(collection, p, o, limit)
|
||||
)
|
||||
|
||||
def get_spo(self, collection, s, p, o, limit=10):
|
||||
# Route to triples_collection table for exact SPO lookup
|
||||
return self.session.execute(
|
||||
self.get_spo_stmt,
|
||||
(collection, s, p, o, limit)
|
||||
)
|
||||
```
|
||||
|
||||
#### Lógica de eliminación de colecciones
|
||||
```python
|
||||
def delete_collection(self, collection):
|
||||
# Step 1: Read all triples from collection table
|
||||
rows = self.session.execute(
|
||||
f"SELECT s, p, o FROM {self.collection_table} WHERE collection = %s",
|
||||
(collection,)
|
||||
)
|
||||
|
||||
# Step 2: Batch delete from all 4 tables
|
||||
batch = BatchStatement()
|
||||
count = 0
|
||||
|
||||
for row in rows:
|
||||
s, p, o = row.s, row.p, row.o
|
||||
|
||||
# Delete using full partition keys for each table
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.subject_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.po_table} WHERE collection = ? AND p = ? AND o = ? AND s = ?"
|
||||
), (collection, p, o, s))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.object_table} WHERE collection = ? AND o = ? AND s = ? AND p = ?"
|
||||
), (collection, o, s, p))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.collection_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
count += 1
|
||||
|
||||
# Execute every 100 triples to avoid oversized batches
|
||||
if count % 100 == 0:
|
||||
self.session.execute(batch)
|
||||
batch = BatchStatement()
|
||||
|
||||
# Execute remaining deletions
|
||||
if count % 100 != 0:
|
||||
self.session.execute(batch)
|
||||
|
||||
logger.info(f"Deleted {count} triples from collection {collection}")
|
||||
```
|
||||
|
||||
#### Optimización de sentencias preparadas
|
||||
```python
|
||||
def prepare_statements(self):
|
||||
# Cache prepared statements for better performance
|
||||
self.insert_subject_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.subject_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_po_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.po_table} (collection, p, o, s) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_object_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.object_table} (collection, o, s, p) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_collection_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.collection_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
# ... query statements
|
||||
```
|
||||
|
||||
## Estrategia de Migración
|
||||
|
||||
### Enfoque de Migración de Datos
|
||||
|
||||
#### Opción 1: Despliegue Blue-Green (Recomendado)
|
||||
1. **Implementar el nuevo esquema junto con el existente** - Utilizar nombres de tabla diferentes temporalmente
|
||||
2. **Período de escritura dual** - Escribir tanto en el esquema antiguo como en el nuevo durante la transición
|
||||
3. **Migración en segundo plano** - Copiar los datos existentes a las nuevas tablas
|
||||
4. **Cambiar las lecturas** - Dirigir las consultas a las nuevas tablas una vez que los datos se hayan migrado
|
||||
5. **Eliminar las tablas antiguas** - Después del período de verificación
|
||||
|
||||
#### Opción 2: Migración In-Place
|
||||
1. **Adición de esquema** - Crear nuevas tablas en el keyspace existente
|
||||
2. **Script de migración de datos** - Copia por lotes de la tabla antigua a las nuevas tablas
|
||||
3. **Actualización de la aplicación** - Implementar el nuevo código después de que se complete la migración
|
||||
4. **Limpieza de la tabla antigua** - Eliminar la tabla antigua e índices
|
||||
|
||||
### Compatibilidad hacia atrás
|
||||
|
||||
#### Estrategia de Despliegue
|
||||
```python
|
||||
# Environment variable to control table usage during migration
|
||||
USE_LEGACY_TABLES = os.getenv('CASSANDRA_USE_LEGACY', 'false').lower() == 'true'
|
||||
|
||||
class KnowledgeGraph:
|
||||
def __init__(self, ...):
|
||||
if USE_LEGACY_TABLES:
|
||||
self.init_legacy_schema()
|
||||
else:
|
||||
self.init_optimized_schema()
|
||||
```
|
||||
|
||||
#### Script de Migración
|
||||
```python
|
||||
def migrate_data():
|
||||
# Read from old table
|
||||
old_triples = session.execute("SELECT collection, s, p, o FROM triples")
|
||||
|
||||
# Batch write to new tables
|
||||
for batch in batched(old_triples, 100):
|
||||
batch_stmt = BatchStatement()
|
||||
for row in batch:
|
||||
# Add to all three new tables
|
||||
batch_stmt.add(insert_subject_stmt, row)
|
||||
batch_stmt.add(insert_po_stmt, (row.collection, row.p, row.o, row.s))
|
||||
batch_stmt.add(insert_object_stmt, (row.collection, row.o, row.s, row.p))
|
||||
session.execute(batch_stmt)
|
||||
```
|
||||
|
||||
### Estrategia de Validación
|
||||
|
||||
#### Comprobaciones de Consistencia de Datos
|
||||
```python
|
||||
def validate_migration():
|
||||
# Count total records in old vs new tables
|
||||
old_count = session.execute("SELECT COUNT(*) FROM triples WHERE collection = ?", (collection,))
|
||||
new_count = session.execute("SELECT COUNT(*) FROM triples_by_subject WHERE collection = ?", (collection,))
|
||||
|
||||
assert old_count == new_count, f"Record count mismatch: {old_count} vs {new_count}"
|
||||
|
||||
# Spot check random samples
|
||||
sample_queries = generate_test_queries()
|
||||
for query in sample_queries:
|
||||
old_result = execute_legacy_query(query)
|
||||
new_result = execute_optimized_query(query)
|
||||
assert old_result == new_result, f"Query results differ for {query}"
|
||||
```
|
||||
|
||||
## Estrategia de Pruebas
|
||||
|
||||
### Pruebas de Rendimiento
|
||||
|
||||
#### Escenarios de Referencia
|
||||
1. **Comparación del Rendimiento de Consultas**
|
||||
Métricas de rendimiento antes y después para los 8 tipos de consultas
|
||||
Centrarse en la mejora del rendimiento de get_po (eliminar ALLOW FILTERING)
|
||||
Medir la latencia de las consultas bajo varios tamaños de datos
|
||||
|
||||
2. **Pruebas de Carga**
|
||||
Ejecución concurrente de consultas
|
||||
Rendimiento de escritura con operaciones por lotes
|
||||
Utilización de memoria y CPU
|
||||
|
||||
3. **Pruebas de Escalabilidad**
|
||||
Rendimiento con tamaños de colección crecientes
|
||||
Distribución de consultas de múltiples colecciones
|
||||
Utilización de nodos del clúster
|
||||
|
||||
#### Conjuntos de Datos de Prueba
|
||||
**Pequeño:** 10K triples por colección
|
||||
**Mediano:** 100K triples por colección
|
||||
**Grande:** 1M+ triples por colección
|
||||
**Múltiples colecciones:** Probar la distribución de particiones
|
||||
|
||||
### Pruebas Funcionales
|
||||
|
||||
#### Actualizaciones de Pruebas Unitarias
|
||||
```python
|
||||
# Example test structure for new implementation
|
||||
class TestCassandraKGPerformance:
|
||||
def test_get_po_no_allow_filtering(self):
|
||||
# Verify get_po queries don't use ALLOW FILTERING
|
||||
with patch('cassandra.cluster.Session.execute') as mock_execute:
|
||||
kg.get_po('test_collection', 'predicate', 'object')
|
||||
executed_query = mock_execute.call_args[0][0]
|
||||
assert 'ALLOW FILTERING' not in executed_query
|
||||
|
||||
def test_multi_table_consistency(self):
|
||||
# Verify all tables stay in sync
|
||||
kg.insert('test', 's1', 'p1', 'o1')
|
||||
|
||||
# Check all tables contain the triple
|
||||
assert_triple_exists('triples_by_subject', 'test', 's1', 'p1', 'o1')
|
||||
assert_triple_exists('triples_by_po', 'test', 'p1', 'o1', 's1')
|
||||
assert_triple_exists('triples_by_object', 'test', 'o1', 's1', 'p1')
|
||||
```
|
||||
|
||||
#### Actualizaciones de la prueba de integración
|
||||
```python
|
||||
class TestCassandraIntegration:
|
||||
def test_query_performance_regression(self):
|
||||
# Ensure new implementation is faster than old
|
||||
old_time = benchmark_legacy_get_po()
|
||||
new_time = benchmark_optimized_get_po()
|
||||
assert new_time < old_time * 0.5 # At least 50% improvement
|
||||
|
||||
def test_end_to_end_workflow(self):
|
||||
# Test complete write -> query -> delete cycle
|
||||
# Verify no performance degradation in integration
|
||||
```
|
||||
|
||||
### Plan de Reversión
|
||||
|
||||
#### Estrategia de Reversión Rápida
|
||||
1. **Alternancia de variables de entorno** - Vuelva a las tablas heredadas inmediatamente.
|
||||
2. **Mantenga las tablas heredadas** - No las elimine hasta que se demuestre el rendimiento.
|
||||
3. **Alertas de monitoreo** - Desencadenadores de reversión automatizados basados en tasas de error/latencia.
|
||||
|
||||
#### Validación de la Reversión
|
||||
```python
|
||||
def rollback_to_legacy():
|
||||
# Set environment variable
|
||||
os.environ['CASSANDRA_USE_LEGACY'] = 'true'
|
||||
|
||||
# Restart services to pick up change
|
||||
restart_cassandra_services()
|
||||
|
||||
# Validate functionality
|
||||
run_smoke_tests()
|
||||
```
|
||||
|
||||
## Riesgos y Consideraciones
|
||||
|
||||
### Riesgos de Rendimiento
|
||||
**Aumento de la latencia de escritura** - 4 operaciones de escritura por inserción (un 33% más que el enfoque de 3 tablas)
|
||||
**Sobrecarga de almacenamiento** - 4 veces más espacio de almacenamiento requerido (un 33% más que el enfoque de 3 tablas)
|
||||
**Fallos en la escritura por lotes** - Se necesita un manejo adecuado de errores
|
||||
**Complejidad de la eliminación** - La eliminación de la colección requiere un bucle de lectura y eliminación
|
||||
|
||||
### Riesgos Operacionales
|
||||
**Complejidad de la migración** - Migración de datos para conjuntos de datos grandes
|
||||
**Desafíos de consistencia** - Asegurar que todas las tablas permanezcan sincronizadas
|
||||
**Lagunas de monitoreo** - Se necesitan nuevas métricas para las operaciones de múltiples tablas
|
||||
|
||||
### Estrategias de Mitigación
|
||||
1. **Implementación gradual** - Comenzar con colecciones pequeñas
|
||||
2. **Monitoreo integral** - Realizar un seguimiento de todas las métricas de rendimiento
|
||||
3. **Validación automatizada** - Verificación continua de la consistencia
|
||||
4. **Capacidad de reversión rápida** - Selección de tablas basada en el entorno
|
||||
|
||||
## Criterios de Éxito
|
||||
|
||||
### Mejoras de Rendimiento
|
||||
[ ] **Eliminar ALLOW FILTERING** - Las consultas get_po y get_os se ejecutan sin filtrado
|
||||
[ ] **Reducción de la latencia de la consulta** - Mejora del 50% o más en los tiempos de respuesta de las consultas
|
||||
[ ] **Mejor distribución de la carga** - Sin particiones "calientes", distribución uniforme de la carga en los nodos del clúster
|
||||
[ ] **Rendimiento escalable** - El tiempo de consulta es proporcional al tamaño del resultado, no a la cantidad total de datos
|
||||
|
||||
### Requisitos Funcionales
|
||||
[ ] **Compatibilidad de la API** - Todo el código existente continúa funcionando sin cambios
|
||||
[ ] **Consistencia de datos** - Las tres tablas permanecen sincronizadas
|
||||
[ ] **Cero pérdida de datos** - La migración preserva todas las triples existentes
|
||||
[ ] **Compatibilidad con versiones anteriores** - Capacidad de volver al esquema heredado
|
||||
|
||||
### Requisitos Operacionales
|
||||
[ ] **Migración segura** - Implementación blue-green con capacidad de reversión
|
||||
[ ] **Cobertura de monitoreo** - Métricas integrales para operaciones de múltiples tablas
|
||||
[ ] **Cobertura de pruebas** - Todos los patrones de consulta se prueban con puntos de referencia de rendimiento
|
||||
[ ] **Documentación** - Procedimientos de implementación y operación actualizados
|
||||
|
||||
## Cronograma
|
||||
|
||||
### Fase 1: Implementación
|
||||
[ ] Reescribir `cassandra_kg.py` con el esquema de múltiples tablas
|
||||
[ ] Implementar operaciones de escritura por lotes
|
||||
[ ] Agregar optimización de sentencias preparadas
|
||||
[ ] Actualizar pruebas unitarias
|
||||
|
||||
### Fase 2: Pruebas de Integración
|
||||
[ ] Actualizar pruebas de integración
|
||||
[ ] Pruebas de rendimiento
|
||||
[ ] Pruebas de carga con volúmenes de datos realistas
|
||||
[ ] Scripts de validación para la consistencia de los datos
|
||||
|
||||
### Fase 3: Planificación de la Migración
|
||||
[ ] Scripts de implementación blue-green
|
||||
[ ] Herramientas de migración de datos
|
||||
[ ] Actualizaciones del panel de monitoreo
|
||||
[ ] Procedimientos de reversión
|
||||
|
||||
### Fase 4: Despliegue en Producción
|
||||
[ ] Implementación gradual en producción
|
||||
[ ] Monitoreo y validación del rendimiento
|
||||
[ ] Limpieza de tablas heredadas
|
||||
[ ] Actualizaciones de la documentación
|
||||
|
||||
## Conclusión
|
||||
|
||||
Esta estrategia de desnormalización de múltiples tablas aborda directamente los dos cuellos de botella de rendimiento críticos:
|
||||
|
||||
1. **Elimina el costoso ALLOW FILTERING** al proporcionar estructuras de tabla óptimas para cada patrón de consulta
|
||||
2. **Mejora la eficacia de la agrupación** a través de claves de partición compuestas que distribuyen la carga de manera adecuada
|
||||
|
||||
El enfoque aprovecha las fortalezas de Cassandra al tiempo que mantiene la compatibilidad total de la API, lo que garantiza que el código existente se beneficie automáticamente de las mejoras de rendimiento.
|
||||
687
docs/tech-specs/cassandra-performance-refactor.he.md
Normal file
687
docs/tech-specs/cassandra-performance-refactor.he.md
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
---
|
||||
layout: default
|
||||
title: "מפרט טכני: שיפור ביצועים של בסיס הידע Cassandra"
|
||||
parent: "Hebrew (Beta)"
|
||||
---
|
||||
|
||||
# מפרט טכני: שיפור ביצועים של בסיס הידע Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**סטטוס:** טיוטה
|
||||
**כותב:** עוזר
|
||||
**תאריך:** 2025-09-18
|
||||
|
||||
## סקירה כללית
|
||||
|
||||
מפרט זה עוסק בבעיות ביצועים ביישום בסיס הידע Cassandra של TrustGraph ומציע אופטימיזציות לאחסון ושליפה של משולשות RDF.
|
||||
|
||||
## יישום נוכחי
|
||||
|
||||
### עיצוב הסכימה
|
||||
|
||||
היישום הנוכחי משתמש בעיצוב טבלה יחידה ב-`trustgraph-flow/trustgraph/direct/cassandra_kg.py`:
|
||||
|
||||
```sql
|
||||
CREATE TABLE triples (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
|
||||
**אינדקסים משניים:**
|
||||
`triples_s` על `s` (נושא)
|
||||
`triples_p` על `p` (נשוא)
|
||||
`triples_o` על `o` (אובייקט)
|
||||
|
||||
### תבניות שאילתה
|
||||
|
||||
המימוש הנוכחי תומך ב-8 תבניות שאילתה מובחנות:
|
||||
|
||||
1. **get_all(collection, limit=50)** - שליפה של כל השלשות עבור אוסף
|
||||
```sql
|
||||
SELECT s, p, o FROM triples WHERE collection = ? LIMIT 50
|
||||
```
|
||||
|
||||
2. **get_s(collection, s, limit=10)** - שאילתה לפי נושא.
|
||||
```sql
|
||||
SELECT p, o FROM triples WHERE collection = ? AND s = ? LIMIT 10
|
||||
```
|
||||
|
||||
3. **get_p(collection, p, limit=10)** - שאילתה לפי תנאי.
|
||||
```sql
|
||||
SELECT s, o FROM triples WHERE collection = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
4. **get_o(collection, o, limit=10)** - שאילתה לפי אובייקט.
|
||||
```sql
|
||||
SELECT s, p FROM triples WHERE collection = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
5. **get_sp(collection, s, p, limit=10)** - שאילתה לפי נושא + טענה
|
||||
```sql
|
||||
SELECT o FROM triples WHERE collection = ? AND s = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
6. **get_po(collection, p, o, limit=10)** - שאילתה לפי תנאי + אובייקט ⚠️
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
7. **get_os(collection, o, s, limit=10)** - שאילתה לפי אובייקט + נושא ⚠️
|
||||
```sql
|
||||
SELECT p FROM triples WHERE collection = ? AND o = ? AND s = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
8. **get_spo(collection, s, p, o, limit=10)** - התאמה מדויקת לשלושה חלקים (subject, predicate, object).
|
||||
```sql
|
||||
SELECT s as x FROM triples WHERE collection = ? AND s = ? AND p = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
### ארכיטקטורה נוכחית
|
||||
|
||||
**קובץ: `trustgraph-flow/trustgraph/direct/cassandra_kg.py`**
|
||||
מחלקה יחידה `KnowledgeGraph` המטפלת בכל הפעולות
|
||||
בריכת חיבורים באמצעות רשימה גלובלית `_active_clusters`
|
||||
שם טבלה קבוע: `"triples"`
|
||||
מרחב מפתחות לכל מודל משתמש
|
||||
שכפול SimpleStrategy עם גורם 1
|
||||
|
||||
**נקודות אינטגרציה:**
|
||||
**נתיב כתיבה:** `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
**נתיב שאילתה:** `trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
**מאגר ידע:** `trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
|
||||
## בעיות ביצועים שזוהו
|
||||
|
||||
### בעיות ברמת הסכימה
|
||||
|
||||
1. **עיצוב מפתח ראשי לא יעיל**
|
||||
נוכחי: `PRIMARY KEY (collection, s, p, o)`
|
||||
גורם לקיבוץ לקוי עבור דפוסי גישה נפוצים
|
||||
מחייב שימוש באינדקסים משניים יקרים
|
||||
|
||||
2. **שימוש יתר באינדקסים משניים** ⚠️
|
||||
שלושה אינדקסים משניים על עמודות עם קרדינליות גבוהה (s, p, o)
|
||||
אינדקסים משניים ב-Cassandra הם יקרים ואינם מתאימים להרחבה
|
||||
שאילתות 6 ו-7 דורשות `ALLOW FILTERING` המצביע על מודל נתונים לקוי
|
||||
|
||||
3. **סיכון לחלוקות חמות**
|
||||
מפתח חלוקה יחיד `collection` יכול ליצור חלוקות חמות
|
||||
אוספים גדולים יתרכזו בצמתים בודדים
|
||||
אין אסטרטגיית חלוקה לאיזון עומסים
|
||||
|
||||
### בעיות ברמת השאילתה
|
||||
|
||||
1. **שימוש ב-ALLOW FILTERING** ⚠️
|
||||
שני סוגי שאילתות (get_po, get_os) דורשים `ALLOW FILTERING`
|
||||
שאילתות אלו סורקות מספר חלוקות ויקרות מאוד
|
||||
הביצועים יורדים באופן ליניארי עם גודל הנתונים
|
||||
|
||||
2. **דפוסי גישה לא יעילים**
|
||||
אין אופטימיזציה עבור דפוסי שאילתות RDF נפוצים
|
||||
חסרים אינדקסים מורכבים עבור שילובים תכופים של שאילתות
|
||||
אין התחשבות בדפוסי מעבר גרפים
|
||||
|
||||
3. **חוסר באופטימיזציה של שאילתות**
|
||||
אין שמירת מטמון של הצהרות מוכנות
|
||||
אין רמזים או אסטרטגיות אופטימיזציה לשאילתות
|
||||
אין התחשבות בדף אחרי דף מעבר לפונקציית LIMIT פשוטה
|
||||
|
||||
## הצהרת בעיה
|
||||
|
||||
ליישום בסיס הידע הנוכחי של Cassandra ישנם שני צווארי בקבוק ביצועים קריטיים:
|
||||
|
||||
### 1. ביצועים לא יעילים של שאילתת get_po
|
||||
|
||||
השאילתה `get_po(collection, p, o)` אינה יעילה מאוד מכיוון שהיא דורשת `ALLOW FILTERING`:
|
||||
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
**מדוע זה בעייתי:**
|
||||
`ALLOW FILTERING` גורם לקסנדרה לסרוק את כל המחיצות בתוך האוסף.
|
||||
הביצועים יורדים באופן ליניארי עם גודל הנתונים.
|
||||
זהו דפוס שאילתות RDF נפוץ (מציאת נושאים שיש להם קשר ספציפי של נשוא-פועל-מושא).
|
||||
זה יוצר עומס משמעותי על האשכול ככל שהנתונים גדלים.
|
||||
|
||||
### 2. אסטרטגיית קיבוץ לקויה
|
||||
|
||||
המפתח הראשי הנוכחי `PRIMARY KEY (collection, s, p, o)` מספק יתרונות קיבוץ מינימליים:
|
||||
|
||||
**בעיות עם הקיבוץ הנוכחי:**
|
||||
`collection` כמפתח מחיצה לא מפזר את הנתונים בצורה יעילה.
|
||||
רוב האוספים מכילים נתונים מגוונים, מה שהופך את הקיבוץ ללא יעיל.
|
||||
אין התחשבות בדפוסי גישה נפוצים בשאילתות RDF.
|
||||
אוספים גדולים יוצרים מחיצות "חמות" על צמתים בודדים.
|
||||
עמודות הקיבוץ (s, p, o) אינן מייעלות עבור דפוסי מעבר גרפים טיפוסיים.
|
||||
|
||||
**השפעה:**
|
||||
שאילתות אינן נהנות ממיקום נתונים.
|
||||
ניצולת מטמון לקויה.
|
||||
חלוקת עומסים לא אחידה בין צמתי האשכול.
|
||||
צווארי בקבוק של יכולת הרחבה ככל שהאוספים גדלים.
|
||||
|
||||
## פתרון מוצע: אסטרטגיית דה-נורמליזציה של 4 טבלאות
|
||||
|
||||
### סקירה כללית
|
||||
|
||||
החליפו את הטבלה הבודדת `triples` בארבע טבלאות ייעודיות, כל אחת מותאמת לדפוסי שאילתות ספציפיים. זה מבטל את הצורך באינדקסים משניים וב-ALLOW FILTERING תוך מתן ביצועים אופטימליים לכל סוגי השאילתות. הטבלה הרביעית מאפשרת מחיקת אוספים יעילה למרות מפתחות מחיצה מורכבים.
|
||||
|
||||
### עיצוב סכימה חדש
|
||||
|
||||
**טבלה 1: שאילתות ממוקדות בנושא (triples_s)**
|
||||
```sql
|
||||
CREATE TABLE triples_s (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY ((collection, s), p, o)
|
||||
);
|
||||
```
|
||||
**משפר:** get_s, get_sp, get_os
|
||||
**מפתח מחיצה:** (collection, s) - פיזור טוב יותר מאשר רק collection
|
||||
**קיבוץ:** (p, o) - מאפשר חיפושים יעילים של טווחים/אובייקטים עבור נושא
|
||||
|
||||
**טבלה 2: שאילתות של טריפלטים (predicate-object) (triples_p)**
|
||||
```sql
|
||||
CREATE TABLE triples_p (
|
||||
collection text,
|
||||
p text,
|
||||
o text,
|
||||
s text,
|
||||
PRIMARY KEY ((collection, p), o, s)
|
||||
);
|
||||
```
|
||||
**משפר:** get_p, get_po (מבטל את ALLOW FILTERING!)
|
||||
**מפתח מחיצה:** (collection, p) - גישה ישירה באמצעות תנאי
|
||||
**קיבוץ:** (o, s) - מעבר יעיל בין אובייקט לנושא
|
||||
|
||||
**טבלה 3: שאילתות ממוקדות אובייקט (triples_o)**
|
||||
```sql
|
||||
CREATE TABLE triples_o (
|
||||
collection text,
|
||||
o text,
|
||||
s text,
|
||||
p text,
|
||||
PRIMARY KEY ((collection, o), s, p)
|
||||
);
|
||||
```
|
||||
**אופטימיזציה:** get_o
|
||||
**מפתח מחיצה:** (collection, o) - גישה ישירה באמצעות אובייקט
|
||||
**קיבוץ:** (s, p) - מעבר יעיל בין נושא ופועל
|
||||
|
||||
**טבלה 4: ניהול אוספים ושאילתות SPO (triples_collection)**
|
||||
```sql
|
||||
CREATE TABLE triples_collection (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
**אופטימיזציה:** get_spo, delete_collection
|
||||
**מפתח מחיצה:** רק אוסף - מאפשר פעולות יעילות ברמת האוסף.
|
||||
**קיבוץ:** (s, p, o) - סדר משולש סטנדרטי.
|
||||
**מטרה:** שימוש כפול לחיפושים מדויקים של SPO וגם כמדד למחיקה.
|
||||
|
||||
### מיפוי שאילתות
|
||||
|
||||
| שאילתה מקורית | טבלה יעד | שיפור ביצועים |
|
||||
|----------------|-------------|------------------------|
|
||||
| get_all(collection) | triples_s | ALLOW FILTERING (מתאים לסריקה) |
|
||||
| get_s(collection, s) | triples_s | גישה ישירה למחיצה |
|
||||
| get_p(collection, p) | triples_p | גישה ישירה למחיצה |
|
||||
| get_o(collection, o) | triples_o | גישה ישירה למחיצה |
|
||||
| get_sp(collection, s, p) | triples_s | מחיצה + קיבוץ |
|
||||
| get_po(collection, p, o) | triples_p | **אין יותר ALLOW FILTERING!** |
|
||||
| get_os(collection, o, s) | triples_o | מחיצה + קיבוץ |
|
||||
| get_spo(collection, s, p, o) | triples_collection | חיפוש מפתח מדויק |
|
||||
| delete_collection(collection) | triples_collection | קריאת מדד, מחיקה אצווה של הכל |
|
||||
|
||||
### אסטרטגיית מחיקת אוסף
|
||||
|
||||
עם מפתחות מחיצה מורכבים, אי אפשר פשוט לבצע `DELETE FROM table WHERE collection = ?`. במקום זאת:
|
||||
|
||||
1. **שלב קריאה:** שאילתא `triples_collection` כדי לרשום את כל המשולשים:
|
||||
```sql
|
||||
SELECT s, p, o FROM triples_collection WHERE collection = ?
|
||||
```
|
||||
זה יעיל מכיוון ש-`collection` הוא מפתח החלוקה עבור הטבלה הזו.
|
||||
|
||||
2. **שלב המחיקה:** עבור כל שלישייה (s, p, o), מחקו מכל 4 הטבלאות תוך שימוש במפתחות חלוקה מלאים:
|
||||
```sql
|
||||
DELETE FROM triples_s WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
DELETE FROM triples_p WHERE collection = ? AND p = ? AND o = ? AND s = ?
|
||||
DELETE FROM triples_o WHERE collection = ? AND o = ? AND s = ? AND p = ?
|
||||
DELETE FROM triples_collection WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
```
|
||||
מחולק לקבוצות של 100 רשומות לטובת יעילות.
|
||||
|
||||
**ניתוח פשרות:**
|
||||
✅ שומר על ביצועי שאילתות אופטימליים עם מחיצות מבוזרות.
|
||||
✅ אין מחיצות עמוסות עבור אוספים גדולים.
|
||||
❌ לוגיקת מחיקה מורכבת יותר (קריאה ואז מחיקה).
|
||||
❌ זמן מחיקה תלוי בגודל האוסף.
|
||||
|
||||
### יתרונות
|
||||
|
||||
1. **מבטל את ALLOW FILTERING** - לכל שאילתה יש נתיב גישה אופטימלי (מלבד סריקת get_all).
|
||||
2. **ללא אינדקסים משניים** - כל טבלה היא האינדקס לדפוס השאילתה שלה.
|
||||
3. **הפצת נתונים טובה יותר** - מפתחות מחיצה מורכבים מפזרים את העומס בצורה יעילה.
|
||||
4. **ביצועים צפויים** - זמן שאילתה תלוי בגודל התוצאה, ולא בגודל הנתונים הכולל.
|
||||
5. **מנצל את החוזקות של Cassandra** - תוכנן עבור ארכיטקטורת Cassandra.
|
||||
6. **מאפשר מחיקת אוספים** - triples_collection משמש כמחירון מחיקה.
|
||||
|
||||
## תוכנית יישום
|
||||
|
||||
### קבצים הדורשים שינוי
|
||||
|
||||
#### קובץ יישום ראשי
|
||||
|
||||
**`trustgraph-flow/trustgraph/direct/cassandra_kg.py`** - נדרש כתיבה מחדש מלאה.
|
||||
|
||||
**שיטות שיש לשכתב:**
|
||||
```python
|
||||
# Schema initialization
|
||||
def init(self) -> None # Replace single table with three tables
|
||||
|
||||
# Insert operations
|
||||
def insert(self, collection, s, p, o) -> None # Write to all three tables
|
||||
|
||||
# Query operations (API unchanged, implementation optimized)
|
||||
def get_all(self, collection, limit=50) # Use triples_by_subject
|
||||
def get_s(self, collection, s, limit=10) # Use triples_by_subject
|
||||
def get_p(self, collection, p, limit=10) # Use triples_by_po
|
||||
def get_o(self, collection, o, limit=10) # Use triples_by_object
|
||||
def get_sp(self, collection, s, p, limit=10) # Use triples_by_subject
|
||||
def get_po(self, collection, p, o, limit=10) # Use triples_by_po (NO ALLOW FILTERING!)
|
||||
def get_os(self, collection, o, s, limit=10) # Use triples_by_subject
|
||||
def get_spo(self, collection, s, p, o, limit=10) # Use triples_by_subject
|
||||
|
||||
# Collection management
|
||||
def delete_collection(self, collection) -> None # Delete from all three tables
|
||||
```
|
||||
|
||||
#### קבצי אינטגרציה (אין צורך בשינויים לוגיים)
|
||||
|
||||
**`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`**
|
||||
אין צורך בשינויים - משתמשים ב-API של KnowledgeGraph הקיים
|
||||
נהנים אוטומטית משיפורי ביצועים
|
||||
|
||||
**`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`**
|
||||
אין צורך בשינויים - משתמשים ב-API של KnowledgeGraph הקיים
|
||||
נהנים אוטומטית משיפורי ביצועים
|
||||
|
||||
### קבצי בדיקה הדורשים עדכונים
|
||||
|
||||
#### בדיקות יחידה
|
||||
**`tests/unit/test_storage/test_triples_cassandra_storage.py`**
|
||||
עדכון ציפיות הבדיקה עבור שינויים בסכימה
|
||||
הוספת בדיקות עבור עקביות בין טבלאות מרובות
|
||||
אימות היעדר ALLOW FILTERING בתוכניות שאילתות
|
||||
|
||||
**`tests/unit/test_query/test_triples_cassandra_query.py`**
|
||||
עדכון טענות ביצועים
|
||||
בדיקת כל 8 דפוסי השאילתות מול טבלאות חדשות
|
||||
אימות ניתוב השאילתות לטבלאות הנכונות
|
||||
|
||||
#### בדיקות אינטגרציה
|
||||
**`tests/integration/test_cassandra_integration.py`**
|
||||
בדיקות מקצה לקצה עם סכימה חדשה
|
||||
השוואות ביצועים
|
||||
אימות עקביות נתונים בין טבלאות
|
||||
|
||||
**`tests/unit/test_storage/test_cassandra_config_integration.py`**
|
||||
עדכון בדיקות אימות סכימה
|
||||
בדיקת תרחישי מעבר
|
||||
|
||||
### אסטרטגיית יישום
|
||||
|
||||
#### שלב 1: סכימה ושיטות ליבה
|
||||
1. **כתיבת מחדש של `init()`** - יצירת ארבע טבלאות במקום אחת
|
||||
2. **כתיבת מחדש של `insert()`** - כתיבה באצווה לכל ארבע הטבלאות
|
||||
3. **יישום הצהרות מוכנות** - לביצועים אופטימליים
|
||||
4. **הוספת לוגיקת ניתוב טבלאות** - הפניית שאילתות לטבלאות האופטימליות
|
||||
5. **יישום מחיקת אוספים** - קריאה מ-triples_collection, מחיקה באצווה מכל הטבלאות
|
||||
|
||||
#### שלב 2: אופטימיזציה של שיטות שאילתה
|
||||
1. **כתיבת מחדש של כל שיטת get_*** לשימוש בטבלה האופטימלית
|
||||
2. **הסרת כל השימושים ב-ALLOW FILTERING**
|
||||
3. **יישום שימוש יעיל במפתח מיון**
|
||||
4. **הוספת רישום ביצועי שאילתות**
|
||||
|
||||
#### שלב 3: ניהול אוספים
|
||||
1. **עדכון `delete_collection()`** - הסרה מכל שלושת הטבלאות
|
||||
2. **הוספת אימות עקביות** - הבטחת סנכרון בין כל הטבלאות
|
||||
3. **יישום פעולות באצווה** - לפעולות מרובות טבלאות אטומיות
|
||||
|
||||
### פרטי יישום מרכזיים
|
||||
|
||||
#### אסטרטגיית כתיבה באצווה
|
||||
```python
|
||||
def insert(self, collection, s, p, o):
|
||||
batch = BatchStatement()
|
||||
|
||||
# Insert into all four tables
|
||||
batch.add(self.insert_subject_stmt, (collection, s, p, o))
|
||||
batch.add(self.insert_po_stmt, (collection, p, o, s))
|
||||
batch.add(self.insert_object_stmt, (collection, o, s, p))
|
||||
batch.add(self.insert_collection_stmt, (collection, s, p, o))
|
||||
|
||||
self.session.execute(batch)
|
||||
```
|
||||
|
||||
#### לוגיקת ניתוב שאילתות
|
||||
```python
|
||||
def get_po(self, collection, p, o, limit=10):
|
||||
# Route to triples_p table - NO ALLOW FILTERING!
|
||||
return self.session.execute(
|
||||
self.get_po_stmt,
|
||||
(collection, p, o, limit)
|
||||
)
|
||||
|
||||
def get_spo(self, collection, s, p, o, limit=10):
|
||||
# Route to triples_collection table for exact SPO lookup
|
||||
return self.session.execute(
|
||||
self.get_spo_stmt,
|
||||
(collection, s, p, o, limit)
|
||||
)
|
||||
```
|
||||
|
||||
#### לוגיקת מחיקת אוספים
|
||||
```python
|
||||
def delete_collection(self, collection):
|
||||
# Step 1: Read all triples from collection table
|
||||
rows = self.session.execute(
|
||||
f"SELECT s, p, o FROM {self.collection_table} WHERE collection = %s",
|
||||
(collection,)
|
||||
)
|
||||
|
||||
# Step 2: Batch delete from all 4 tables
|
||||
batch = BatchStatement()
|
||||
count = 0
|
||||
|
||||
for row in rows:
|
||||
s, p, o = row.s, row.p, row.o
|
||||
|
||||
# Delete using full partition keys for each table
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.subject_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.po_table} WHERE collection = ? AND p = ? AND o = ? AND s = ?"
|
||||
), (collection, p, o, s))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.object_table} WHERE collection = ? AND o = ? AND s = ? AND p = ?"
|
||||
), (collection, o, s, p))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.collection_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
count += 1
|
||||
|
||||
# Execute every 100 triples to avoid oversized batches
|
||||
if count % 100 == 0:
|
||||
self.session.execute(batch)
|
||||
batch = BatchStatement()
|
||||
|
||||
# Execute remaining deletions
|
||||
if count % 100 != 0:
|
||||
self.session.execute(batch)
|
||||
|
||||
logger.info(f"Deleted {count} triples from collection {collection}")
|
||||
```
|
||||
|
||||
#### אופטימיזציה של הצהרת הכנה (Prepared Statement)
|
||||
```python
|
||||
def prepare_statements(self):
|
||||
# Cache prepared statements for better performance
|
||||
self.insert_subject_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.subject_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_po_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.po_table} (collection, p, o, s) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_object_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.object_table} (collection, o, s, p) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_collection_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.collection_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
# ... query statements
|
||||
```
|
||||
|
||||
## אסטרטגיית מעבר
|
||||
|
||||
### גישת מעבר נתונים
|
||||
|
||||
#### אפשרות 1: פריסה בצבע כחול-ירוק (מומלץ)
|
||||
1. **פריסת הסכימה החדשה לצד הקיימת** - השתמש בשמות טבלאות שונים באופן זמני
|
||||
2. **תקופת כתיבה כפולה** - כתיבה גם לסכימה הישנה וגם לחדשה במהלך המעבר
|
||||
3. **מעבר נתונים ברקע** - העתקת נתונים קיימים לטבלאות חדשות
|
||||
4. **הפניית שאילתות** - הפניית שאילתות לטבלאות החדשות לאחר שהנתונים עברו
|
||||
5. **מחיקת הטבלאות הישנות** - לאחר תקופת אימות
|
||||
|
||||
#### אפשרות 2: מעבר במקום
|
||||
1. **הוספת סכימה** - יצירת טבלאות חדשות במרחב מפתחות קיים
|
||||
2. **סקריפט מעבר נתונים** - העתקה באצווה מטבלה ישנה לטבלאות חדשות
|
||||
3. **עדכון יישום** - פריסת קוד חדש לאחר השלמת המעבר
|
||||
4. **ניקוי הטבלה הישנה** - הסרת הטבלה הישנה והאינדקסים
|
||||
|
||||
### תאימות לאחור
|
||||
|
||||
#### אסטרטגיית פריסה
|
||||
```python
|
||||
# Environment variable to control table usage during migration
|
||||
USE_LEGACY_TABLES = os.getenv('CASSANDRA_USE_LEGACY', 'false').lower() == 'true'
|
||||
|
||||
class KnowledgeGraph:
|
||||
def __init__(self, ...):
|
||||
if USE_LEGACY_TABLES:
|
||||
self.init_legacy_schema()
|
||||
else:
|
||||
self.init_optimized_schema()
|
||||
```
|
||||
|
||||
#### סקריפט הגירה
|
||||
```python
|
||||
def migrate_data():
|
||||
# Read from old table
|
||||
old_triples = session.execute("SELECT collection, s, p, o FROM triples")
|
||||
|
||||
# Batch write to new tables
|
||||
for batch in batched(old_triples, 100):
|
||||
batch_stmt = BatchStatement()
|
||||
for row in batch:
|
||||
# Add to all three new tables
|
||||
batch_stmt.add(insert_subject_stmt, row)
|
||||
batch_stmt.add(insert_po_stmt, (row.collection, row.p, row.o, row.s))
|
||||
batch_stmt.add(insert_object_stmt, (row.collection, row.o, row.s, row.p))
|
||||
session.execute(batch_stmt)
|
||||
```
|
||||
|
||||
### אסטרטגיית אימות
|
||||
|
||||
#### בדיקות עקביות נתונים
|
||||
```python
|
||||
def validate_migration():
|
||||
# Count total records in old vs new tables
|
||||
old_count = session.execute("SELECT COUNT(*) FROM triples WHERE collection = ?", (collection,))
|
||||
new_count = session.execute("SELECT COUNT(*) FROM triples_by_subject WHERE collection = ?", (collection,))
|
||||
|
||||
assert old_count == new_count, f"Record count mismatch: {old_count} vs {new_count}"
|
||||
|
||||
# Spot check random samples
|
||||
sample_queries = generate_test_queries()
|
||||
for query in sample_queries:
|
||||
old_result = execute_legacy_query(query)
|
||||
new_result = execute_optimized_query(query)
|
||||
assert old_result == new_result, f"Query results differ for {query}"
|
||||
```
|
||||
|
||||
## אסטרטגיית בדיקות
|
||||
|
||||
### בדיקות ביצועים
|
||||
|
||||
#### תרחישי ביצוע
|
||||
1. **השוואת ביצועי שאילתות**
|
||||
מדדי ביצועים לפני ואחרי עבור כל 8 סוגי השאילתות
|
||||
התמקדות בשיפור ביצועים של שאילתת get_po (הסרת ALLOW FILTERING)
|
||||
מדידת השהייה של שאילתות בתנאי גדלי נתונים שונים
|
||||
|
||||
2. **בדיקות עומסים**
|
||||
ביצוע שאילתות במקביל
|
||||
קצב כתיבה עם פעולות אצווה
|
||||
ניצול זיכרון ו-CPU
|
||||
|
||||
3. **בדיקות סקלאביליות**
|
||||
ביצועים עם גדלי אוספים גדלים
|
||||
חלוקת שאילתות בין אוספים מרובים
|
||||
ניצול צמתים באשכול
|
||||
|
||||
#### סטי נתוני בדיקה
|
||||
**קטן:** 10 אלף משולשים לאוסף
|
||||
**בינוני:** 100 אלף משולשים לאוסף
|
||||
**גדול:** 1 מיליון+ משולשים לאוסף
|
||||
**אוספים מרובים:** בדיקת חלוקת מחיצות
|
||||
|
||||
### בדיקות פונקציונליות
|
||||
|
||||
#### עדכוני בדיקות יחידה
|
||||
```python
|
||||
# Example test structure for new implementation
|
||||
class TestCassandraKGPerformance:
|
||||
def test_get_po_no_allow_filtering(self):
|
||||
# Verify get_po queries don't use ALLOW FILTERING
|
||||
with patch('cassandra.cluster.Session.execute') as mock_execute:
|
||||
kg.get_po('test_collection', 'predicate', 'object')
|
||||
executed_query = mock_execute.call_args[0][0]
|
||||
assert 'ALLOW FILTERING' not in executed_query
|
||||
|
||||
def test_multi_table_consistency(self):
|
||||
# Verify all tables stay in sync
|
||||
kg.insert('test', 's1', 'p1', 'o1')
|
||||
|
||||
# Check all tables contain the triple
|
||||
assert_triple_exists('triples_by_subject', 'test', 's1', 'p1', 'o1')
|
||||
assert_triple_exists('triples_by_po', 'test', 'p1', 'o1', 's1')
|
||||
assert_triple_exists('triples_by_object', 'test', 'o1', 's1', 'p1')
|
||||
```
|
||||
|
||||
#### עדכונים לבדיקות אינטגרציה
|
||||
```python
|
||||
class TestCassandraIntegration:
|
||||
def test_query_performance_regression(self):
|
||||
# Ensure new implementation is faster than old
|
||||
old_time = benchmark_legacy_get_po()
|
||||
new_time = benchmark_optimized_get_po()
|
||||
assert new_time < old_time * 0.5 # At least 50% improvement
|
||||
|
||||
def test_end_to_end_workflow(self):
|
||||
# Test complete write -> query -> delete cycle
|
||||
# Verify no performance degradation in integration
|
||||
```
|
||||
|
||||
### תוכנית חזרה אחורה
|
||||
|
||||
#### אסטרטגיה מהירה לחזרה אחורה
|
||||
1. **החלפת משתנה סביבה** - חזרה מיידית לטבלאות הישנות.
|
||||
2. **שמירה על הטבלאות הישנות** - לא למחוק עד שיוכח שיפור בביצועים.
|
||||
3. **התראות ניטור** - הפעלת חזרה אוטומטית בהתבסס על שיעורי שגיאות/השהייה.
|
||||
|
||||
#### אימות חזרה אחורה
|
||||
```python
|
||||
def rollback_to_legacy():
|
||||
# Set environment variable
|
||||
os.environ['CASSANDRA_USE_LEGACY'] = 'true'
|
||||
|
||||
# Restart services to pick up change
|
||||
restart_cassandra_services()
|
||||
|
||||
# Validate functionality
|
||||
run_smoke_tests()
|
||||
```
|
||||
|
||||
## סיכונים ושיקולים
|
||||
|
||||
### סיכוני ביצועים
|
||||
**עלייה בלעדי כתיבה** - 4 פעולות כתיבה לכל הוספה (33% יותר מהגישה של 3 טבלאות)
|
||||
**תקורת אחסון** - דרישת אחסון של 4x (33% יותר מהגישה של 3 טבלאות)
|
||||
**כשלים בכתיבה אצווה** - יש צורך בטיפול תקין בשגיאות
|
||||
**מורכבות מחיקה** - מחיקת אוסף דורשת לולאה של קריאה ולאחר מכן מחיקה
|
||||
|
||||
### סיכונים תפעוליים
|
||||
**מורכבות העברה** - העברת נתונים עבור מערכי נתונים גדולים
|
||||
**אתגרים של עקביות** - הבטחת סנכרון של כל הטבלאות
|
||||
**פערים בניטור** - יש צורך במדדים חדשים עבור פעולות מרובות טבלאות
|
||||
|
||||
### אסטרטגיות הפחתת סיכונים
|
||||
1. **פריסה הדרגתית** - התחילו עם אוספים קטנים
|
||||
2. **ניטור מקיף** - מעקב אחר כל מדדי הביצועים
|
||||
3. **אימות אוטומטי** - בדיקת עקביות רציפה
|
||||
4. **יכולת ביטול מהירה** - בחירת טבלה מבוססת סביבה
|
||||
|
||||
## קריטריוני הצלחה
|
||||
|
||||
### שיפורי ביצועים
|
||||
[ ] **ביטול ALLOW FILTERING** - שאילתות get_po ו-get_os פועלות ללא סינון
|
||||
[ ] **הפחתת השהייה בשאילתות** - שיפור של 50%+ בזמני תגובה של שאילתות
|
||||
[ ] **חלוקת עומסים טובה יותר** - ללא מחיצות "חמות", חלוקת עומסים שווה על פני צמתים בקלאסטר
|
||||
[ ] **ביצועים ניתנים להרחבה** - זמן שאילתה תלוי בגודל התוצאה, ולא בנפח הנתונים הכולל
|
||||
|
||||
### דרישות פונקציונליות
|
||||
[ ] **תאימות API** - כל הקוד הקיים ממשיך לעבוד ללא שינוי
|
||||
[ ] **עקביות נתונים** - שלוש הטבלאות נשארות מסונכרנות
|
||||
[ ] **אפס אובדן נתונים** - העברה שומרת על כל הטרפלים הקיימים
|
||||
[ ] **תאימות לאחור** - אפשרות לחזור לסקמה הישנה
|
||||
|
||||
### דרישות תפעוליות
|
||||
[ ] **העברה בטוחה** - פריסה בצורה כחולה-ירוקה עם יכולת ביטול
|
||||
[ ] **כיסוי ניטור** - מדדים מקיפים עבור פעולות מרובות טבלאות
|
||||
[ ] **כיסוי בדיקות** - כל דפוסי השאילתות נבדקו עם מדדי ביצועים
|
||||
[ ] **תיעוד** - עדכון נהלי פריסה ותפעול
|
||||
|
||||
## ציר זמן
|
||||
|
||||
### שלב 1: יישום
|
||||
[ ] כתיבה מחדש של `cassandra_kg.py` עם סכימת טבלאות מרובות
|
||||
[ ] יישום פעולות כתיבה אצווה
|
||||
[ ] הוספת אופטימיזציה של הצהרות מוכנות
|
||||
[ ] עדכון בדיקות יחידה
|
||||
|
||||
### שלב 2: בדיקות אינטגרציה
|
||||
[ ] עדכון בדיקות אינטגרציה
|
||||
[ ] מדידת ביצועים
|
||||
[ ] בדיקת עומסים עם נפחי נתונים ריאליים
|
||||
[ ] סקריפטים לאימות עקביות נתונים
|
||||
|
||||
### שלב 3: תכנון העברה
|
||||
[ ] סקריפטים לפריסה בצורה כחולה-ירוקה
|
||||
[ ] כלים להעברת נתונים
|
||||
[ ] עדכוני לוח מחוונים לניטור
|
||||
[ ] נהלי ביטול
|
||||
|
||||
### שלב 4: פריסה לייצור
|
||||
[ ] פריסה הדרגתית לסביבת ייצור
|
||||
[ ] ניטור ואימות ביצועים
|
||||
[ ] ניקוי טבלאות ישנות
|
||||
[ ] עדכוני תיעוד
|
||||
|
||||
## מסקנה
|
||||
|
||||
אסטרטגיית הדה-נורמליזציה מרובת טבלאות פותרת ישירות את שני צווארי הבקבוק הקריטיים בביצועים:
|
||||
|
||||
1. **מבטלת את ALLOW FILTERING היקר** על ידי מתן מבני טבלאות אופטימליים עבור כל דפוס שאילתה
|
||||
2. **משפרת את יעילות הקיבוץ** באמצעות מפתחות מחיצה מורכבים שמפיצים את העומס כראוי
|
||||
|
||||
הגישה ממנפת את החוזקות של Cassandra תוך שמירה על תאימות API מלאה, ומבטיחה שלקוד הקיים יש יתרונות אוטומטיים משיפורי הביצועים.
|
||||
687
docs/tech-specs/cassandra-performance-refactor.hi.md
Normal file
687
docs/tech-specs/cassandra-performance-refactor.hi.md
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
---
|
||||
layout: default
|
||||
title: "तकनीकी विनिर्देश: कैसेंड्रा नॉलेज बेस प्रदर्शन पुनर्निर्माण"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# तकनीकी विनिर्देश: कैसेंड्रा नॉलेज बेस प्रदर्शन पुनर्निर्माण
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**स्थिति:** मसौदा
|
||||
**लेखक:** सहायक
|
||||
**तिथि:** 2025-09-18
|
||||
|
||||
## अवलोकन
|
||||
|
||||
यह विनिर्देश ट्रस्टग्राफ कैसेंड्रा नॉलेज बेस कार्यान्वयन में प्रदर्शन संबंधी मुद्दों को संबोधित करता है और आरडीएफ ट्रिपल भंडारण और क्वेरी के लिए अनुकूलन प्रस्तावित करता है।
|
||||
|
||||
## वर्तमान कार्यान्वयन
|
||||
|
||||
### स्कीमा डिज़ाइन
|
||||
|
||||
वर्तमान कार्यान्वयन `trustgraph-flow/trustgraph/direct/cassandra_kg.py` में एक एकल तालिका डिज़ाइन का उपयोग करता है:
|
||||
|
||||
```sql
|
||||
CREATE TABLE triples (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
|
||||
**माध्यमिक अनुक्रमणिकाएँ:**
|
||||
`triples_s` ON `s` (विषय)
|
||||
`triples_p` ON `p` (क्रिया)
|
||||
`triples_o` ON `o` (वस्तु)
|
||||
|
||||
### क्वेरी पैटर्न
|
||||
|
||||
वर्तमान कार्यान्वयन 8 अलग-अलग क्वेरी पैटर्न का समर्थन करता है:
|
||||
|
||||
1. **get_all(संग्रह, सीमा=50)** - एक संग्रह के लिए सभी त्रिगुट प्राप्त करें
|
||||
```sql
|
||||
SELECT s, p, o FROM triples WHERE collection = ? LIMIT 50
|
||||
```
|
||||
|
||||
2. **get_s(संग्रह, s, सीमा=10)** - विषय द्वारा खोज।
|
||||
```sql
|
||||
SELECT p, o FROM triples WHERE collection = ? AND s = ? LIMIT 10
|
||||
```
|
||||
|
||||
3. **get_p(संग्रह, p, सीमा=10)** - विधेय द्वारा खोज
|
||||
```sql
|
||||
SELECT s, o FROM triples WHERE collection = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
4. **get_o(संग्रह, o, सीमा=10)** - ऑब्जेक्ट द्वारा क्वेरी करें।
|
||||
```sql
|
||||
SELECT s, p FROM triples WHERE collection = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
5. **get_sp(संग्रह, s, p, सीमा=10)** - विषय + विधेय द्वारा खोज।
|
||||
```sql
|
||||
SELECT o FROM triples WHERE collection = ? AND s = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
6. **get_po(collection, p, o, limit=10)** - पूर्व निर्धारित शर्तों और वस्तुओं के आधार पर खोज ⚠️
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
7. **get_os(संग्रह, o, s, सीमा=10)** - ऑब्जेक्ट + विषय द्वारा क्वेरी ⚠️
|
||||
```sql
|
||||
SELECT p FROM triples WHERE collection = ? AND o = ? AND s = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
8. **get_spo(संग्रह, s, p, o, सीमा=10)** - सटीक त्रिगुट मिलान
|
||||
```sql
|
||||
SELECT s as x FROM triples WHERE collection = ? AND s = ? AND p = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
### वर्तमान आर्किटेक्चर
|
||||
|
||||
**फ़ाइल: `trustgraph-flow/trustgraph/direct/cassandra_kg.py`**
|
||||
सभी कार्यों को संभालने वाली एकल `KnowledgeGraph` क्लास
|
||||
वैश्विक `_active_clusters` सूची के माध्यम से कनेक्शन पूलिंग
|
||||
निश्चित टेबल नाम: `"triples"`
|
||||
प्रति उपयोगकर्ता मॉडल के लिए कीस्पेस
|
||||
फैक्टर 1 के साथ सिंपलस्ट्रैटेजी प्रतिकृति
|
||||
|
||||
**एकीकरण बिंदु:**
|
||||
**राइट पाथ:** `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
**क्वेरी पाथ:** `trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
**नॉलेज स्टोर:** `trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
|
||||
## पहचाने गए प्रदर्शन संबंधी मुद्दे
|
||||
|
||||
### स्कीमा-स्तरीय मुद्दे
|
||||
|
||||
1. **अकुशल प्राइमरी की डिज़ाइन**
|
||||
वर्तमान: `PRIMARY KEY (collection, s, p, o)`
|
||||
सामान्य एक्सेस पैटर्न के लिए खराब क्लस्टरिंग का कारण बनता है
|
||||
महंगे सेकेंडरी इंडेक्स के उपयोग को मजबूर करता है
|
||||
|
||||
2. **सेकेंडरी इंडेक्स का अत्यधिक उपयोग** ⚠️
|
||||
उच्च कार्डिनलिटी कॉलम (s, p, o) पर तीन सेकेंडरी इंडेक्स
|
||||
कैसेंड्रा में सेकेंडरी इंडेक्स महंगे होते हैं और अच्छी तरह से स्केल नहीं होते हैं
|
||||
क्वेरी 6 और 7 को `ALLOW FILTERING` की आवश्यकता होती है, जो खराब डेटा मॉडलिंग का संकेत देती है
|
||||
|
||||
3. **हॉट पार्टिशन का जोखिम**
|
||||
एकल पार्टीशन कुंजी `collection` हॉट पार्टिशन बना सकती है
|
||||
बड़े संग्रह एकल नोड्स पर केंद्रित होंगे
|
||||
लोड बैलेंसिंग के लिए कोई वितरण रणनीति नहीं
|
||||
|
||||
### क्वेरी-स्तरीय मुद्दे
|
||||
|
||||
1. **ALLOW FILTERING का उपयोग** ⚠️
|
||||
दो क्वेरी प्रकार (get_po, get_os) को `ALLOW FILTERING` की आवश्यकता होती है
|
||||
ये क्वेरी कई पार्टिशन को स्कैन करती हैं और बेहद महंगी हैं
|
||||
डेटा के आकार के साथ प्रदर्शन रैखिक रूप से खराब होता है
|
||||
|
||||
2. **अकुशल एक्सेस पैटर्न**
|
||||
सामान्य आरडीएफ क्वेरी पैटर्न के लिए कोई अनुकूलन नहीं
|
||||
बार-बार उपयोग किए जाने वाले क्वेरी संयोजनों के लिए कोई कंपाउंड इंडेक्स नहीं
|
||||
ग्राफ ट्रैवर्सल पैटर्न पर कोई विचार नहीं
|
||||
|
||||
3. **क्वेरी अनुकूलन की कमी**
|
||||
कोई तैयार स्टेटमेंट कैशिंग नहीं
|
||||
कोई क्वेरी संकेत या अनुकूलन रणनीतियाँ नहीं
|
||||
साधारण LIMIT से परे पेजिंग पर कोई विचार नहीं
|
||||
|
||||
## समस्या विवरण
|
||||
|
||||
वर्तमान कैसेंड्रा नॉलेज बेस कार्यान्वयन में दो महत्वपूर्ण प्रदर्शन संबंधी बाधाएं हैं:
|
||||
|
||||
### 1. अकुशल get_po क्वेरी प्रदर्शन
|
||||
|
||||
`get_po(collection, p, o)` क्वेरी `ALLOW FILTERING` की आवश्यकता के कारण बेहद अकुशल है:
|
||||
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
**यह समस्याग्रस्त क्यों है:**
|
||||
`ALLOW FILTERING` कैसेंड्रा को संग्रह के भीतर सभी विभाजन को स्कैन करने के लिए मजबूर करता है।
|
||||
डेटा के आकार के साथ प्रदर्शन रैखिक रूप से घटता है।
|
||||
यह एक सामान्य आरडीएफ क्वेरी पैटर्न है (उन विषयों को खोजना जिनके पास एक विशिष्ट विधेय-वस्तु संबंध है)।
|
||||
जैसे-जैसे डेटा बढ़ता है, यह क्लस्टर पर महत्वपूर्ण भार डालता है।
|
||||
|
||||
### 2. खराब क्लस्टरिंग रणनीति
|
||||
|
||||
वर्तमान प्राथमिक कुंजी `PRIMARY KEY (collection, s, p, o)` न्यूनतम क्लस्टरिंग लाभ प्रदान करती है:
|
||||
|
||||
**वर्तमान क्लस्टरिंग के साथ समस्याएं:**
|
||||
विभाजन कुंजी के रूप में `collection` डेटा को प्रभावी ढंग से वितरित नहीं करता है।
|
||||
अधिकांश संग्रहों में विविध डेटा होता है, जिससे क्लस्टरिंग अप्रभावी हो जाती है।
|
||||
आरडीएफ प्रश्नों में सामान्य एक्सेस पैटर्न पर कोई विचार नहीं किया गया है।
|
||||
बड़े संग्रह एकल नोड्स पर "हॉट" विभाजन बनाते हैं।
|
||||
क्लस्टरिंग कॉलम (s, p, o) विशिष्ट ग्राफ ट्रैवर्सल पैटर्न के लिए अनुकूलित नहीं हैं।
|
||||
|
||||
**प्रभाव:**
|
||||
क्वेरी डेटा स्थानीयता से लाभान्वित नहीं होती हैं।
|
||||
खराब कैश उपयोग।
|
||||
क्लस्टर नोड्स में असमान लोड वितरण।
|
||||
जैसे-जैसे संग्रह बढ़ते हैं, स्केलेबिलिटी बाधाएं।
|
||||
|
||||
## प्रस्तावित समाधान: 4-टेबल डीनॉर्मलाइज़ेशन रणनीति
|
||||
|
||||
### अवलोकन
|
||||
|
||||
एकल `triples` तालिका को चार उद्देश्य-निर्मित तालिकाओं से बदलें, प्रत्येक विशिष्ट क्वेरी पैटर्न के लिए अनुकूलित है। यह द्वितीयक अनुक्रमणिकाओं और ALLOW FILTERING की आवश्यकता को समाप्त करता है, जबकि सभी प्रकार की क्वेरी के लिए इष्टतम प्रदर्शन प्रदान करता है। चौथी तालिका समग्र विभाजन कुंजियों के बावजूद कुशल संग्रह हटाने को सक्षम बनाती है।
|
||||
|
||||
### नया स्कीमा डिज़ाइन
|
||||
|
||||
**टेबल 1: विषय-केंद्रित क्वेरी (triples_s)**
|
||||
```sql
|
||||
CREATE TABLE triples_s (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY ((collection, s), p, o)
|
||||
);
|
||||
```
|
||||
**अनुकूलन:** get_s, get_sp, get_os
|
||||
**विभाजन कुंजी:** (संग्रह, s) - केवल संग्रह की तुलना में बेहतर वितरण
|
||||
**समूहीकरण:** (p, o) - विषय के लिए कुशल विधेय/वस्तु लुकअप को सक्षम करता है
|
||||
|
||||
**तालिका 2: विधेय-वस्तु प्रश्न (triples_p)**
|
||||
```sql
|
||||
CREATE TABLE triples_p (
|
||||
collection text,
|
||||
p text,
|
||||
o text,
|
||||
s text,
|
||||
PRIMARY KEY ((collection, p), o, s)
|
||||
);
|
||||
```
|
||||
**अनुकूलन:** get_p, get_po (ALLOW FILTERING को हटाता है!)
|
||||
**पार्टिशन कुंजी:** (संग्रह, p) - विधेय द्वारा प्रत्यक्ष पहुंच
|
||||
**क्लस्टरिंग:** (o, s) - कुशल ऑब्जेक्ट-विषय ट्रैवर्सल
|
||||
|
||||
**तालिका 3: ऑब्जेक्ट-केंद्रित प्रश्न (triples_o)**
|
||||
```sql
|
||||
CREATE TABLE triples_o (
|
||||
collection text,
|
||||
o text,
|
||||
s text,
|
||||
p text,
|
||||
PRIMARY KEY ((collection, o), s, p)
|
||||
);
|
||||
```
|
||||
**अनुकूलन:** get_o
|
||||
**विभाजन कुंजी:** (संग्रह, o) - वस्तु द्वारा प्रत्यक्ष पहुंच
|
||||
**समूहीकरण:** (s, p) - कुशल विषय-क्रियापद ट्रैवर्सल
|
||||
|
||||
**तालिका 4: संग्रह प्रबंधन और एस.पी.ओ. प्रश्न (triples_collection)**
|
||||
```sql
|
||||
CREATE TABLE triples_collection (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
**अनुकूलन:** get_spo, delete_collection
|
||||
**विभाजन कुंजी:** केवल संग्रह - कुशल संग्रह-स्तरीय संचालन को सक्षम करता है
|
||||
**समूहीकरण:** (s, p, o) - मानक त्रिगुट क्रम
|
||||
**उद्देश्य:** सटीक SPO लुकअप के लिए दोहरे उपयोग और एक हटाने अनुक्रमणिका के रूप में
|
||||
|
||||
### क्वेरी मैपिंग
|
||||
|
||||
| मूल क्वेरी | लक्ष्य तालिका | प्रदर्शन सुधार |
|
||||
|----------------|-------------|------------------------|
|
||||
| get_all(संग्रह) | triples_s | ALLOW FILTERING (स्कैन के लिए स्वीकार्य) |
|
||||
| get_s(संग्रह, s) | triples_s | प्रत्यक्ष विभाजन पहुंच |
|
||||
| get_p(संग्रह, p) | triples_p | प्रत्यक्ष विभाजन पहुंच |
|
||||
| get_o(संग्रह, o) | triples_o | प्रत्यक्ष विभाजन पहुंच |
|
||||
| get_sp(संग्रह, s, p) | triples_s | विभाजन + समूहीकरण |
|
||||
| get_po(संग्रह, p, o) | triples_p | **अब ALLOW FILTERING नहीं!** |
|
||||
| get_os(संग्रह, o, s) | triples_o | विभाजन + समूहीकरण |
|
||||
| get_spo(संग्रह, s, p, o) | triples_collection | सटीक कुंजी लुकअप |
|
||||
| delete_collection(संग्रह) | triples_collection | अनुक्रमणिका पढ़ें, सभी को बैच में हटाएं |
|
||||
|
||||
### संग्रह हटाने की रणनीति
|
||||
|
||||
संयुक्त विभाजन कुंजियों के साथ, हम सीधे `DELETE FROM table WHERE collection = ?` निष्पादित नहीं कर सकते। इसके बजाय:
|
||||
|
||||
1. **पढ़ने का चरण:** सभी त्रिगुटों को सूचीबद्ध करने के लिए `triples_collection` क्वेरी करें:
|
||||
```sql
|
||||
SELECT s, p, o FROM triples_collection WHERE collection = ?
|
||||
```
|
||||
यह कुशल है क्योंकि `collection` इस तालिका के लिए विभाजन कुंजी है।
|
||||
|
||||
2. **हटाने का चरण:** प्रत्येक ट्रिपल (s, p, o) के लिए, सभी 4 तालिकाओं से पूर्ण विभाजन कुंजियों का उपयोग करके हटाएं:
|
||||
```sql
|
||||
DELETE FROM triples_s WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
DELETE FROM triples_p WHERE collection = ? AND p = ? AND o = ? AND s = ?
|
||||
DELETE FROM triples_o WHERE collection = ? AND o = ? AND s = ? AND p = ?
|
||||
DELETE FROM triples_collection WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
```
|
||||
दक्षता के लिए 100 के समूहों में समूहीकृत किया गया।
|
||||
|
||||
**ट्रेड-ऑफ विश्लेषण:**
|
||||
✅ वितरित विभाजनों के साथ इष्टतम क्वेरी प्रदर्शन बनाए रखता है।
|
||||
✅ बड़े संग्रहों के लिए कोई "हॉट" विभाजन नहीं।
|
||||
❌ अधिक जटिल हटाने का तर्क (पढ़ें-फिर-हटाएं)।
|
||||
❌ हटाने का समय संग्रह के आकार के समानुपाती होता है।
|
||||
|
||||
### लाभ
|
||||
|
||||
1. **ALLOW FILTERING को समाप्त करता है** - प्रत्येक क्वेरी में एक इष्टतम एक्सेस पथ होता है (सिवाय get_all स्कैन के)।
|
||||
2. **कोई द्वितीयक इंडेक्स नहीं** - प्रत्येक तालिका अपने क्वेरी पैटर्न के लिए इंडेक्स है।
|
||||
3. **बेहतर डेटा वितरण** - समग्र विभाजन कुंजियाँ प्रभावी रूप से लोड फैलाती हैं।
|
||||
4. **अनुमानित प्रदर्शन** - क्वेरी समय परिणाम के आकार के समानुपाती होता है, कुल डेटा के नहीं।
|
||||
5. **कैसेंड्रा की ताकत का लाभ उठाता है** - कैसेंड्रा के आर्किटेक्चर के लिए डिज़ाइन किया गया।
|
||||
6. **संग्रह हटाने को सक्षम बनाता है** - triples_collection हटाने के इंडेक्स के रूप में कार्य करता है।
|
||||
|
||||
## कार्यान्वयन योजना
|
||||
|
||||
### उन फ़ाइलों की आवश्यकता है जिनमें परिवर्तन आवश्यक हैं
|
||||
|
||||
#### प्राथमिक कार्यान्वयन फ़ाइल
|
||||
|
||||
**`trustgraph-flow/trustgraph/direct/cassandra_kg.py`** - पूर्ण पुनर्लेखन आवश्यक है।
|
||||
|
||||
**वर्तमान विधियाँ जिन्हें रिफैक्टर करने की आवश्यकता है:**
|
||||
```python
|
||||
# Schema initialization
|
||||
def init(self) -> None # Replace single table with three tables
|
||||
|
||||
# Insert operations
|
||||
def insert(self, collection, s, p, o) -> None # Write to all three tables
|
||||
|
||||
# Query operations (API unchanged, implementation optimized)
|
||||
def get_all(self, collection, limit=50) # Use triples_by_subject
|
||||
def get_s(self, collection, s, limit=10) # Use triples_by_subject
|
||||
def get_p(self, collection, p, limit=10) # Use triples_by_po
|
||||
def get_o(self, collection, o, limit=10) # Use triples_by_object
|
||||
def get_sp(self, collection, s, p, limit=10) # Use triples_by_subject
|
||||
def get_po(self, collection, p, o, limit=10) # Use triples_by_po (NO ALLOW FILTERING!)
|
||||
def get_os(self, collection, o, s, limit=10) # Use triples_by_subject
|
||||
def get_spo(self, collection, s, p, o, limit=10) # Use triples_by_subject
|
||||
|
||||
# Collection management
|
||||
def delete_collection(self, collection) -> None # Delete from all three tables
|
||||
```
|
||||
|
||||
#### एकीकरण फ़ाइलें (कोई लॉजिक परिवर्तन आवश्यक नहीं)
|
||||
|
||||
**`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`**
|
||||
कोई बदलाव आवश्यक नहीं - मौजूदा नॉलेज ग्राफ एपीआई का उपयोग करता है
|
||||
प्रदर्शन में स्वचालित सुधार से लाभ
|
||||
|
||||
**`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`**
|
||||
कोई बदलाव आवश्यक नहीं - मौजूदा नॉलेज ग्राफ एपीआई का उपयोग करता है
|
||||
प्रदर्शन में स्वचालित सुधार से लाभ
|
||||
|
||||
### अपडेट की आवश्यकता वाली परीक्षण फ़ाइलें
|
||||
|
||||
#### यूनिट टेस्ट
|
||||
**`tests/unit/test_storage/test_triples_cassandra_storage.py`**
|
||||
स्कीमा परिवर्तनों के लिए परीक्षण अपेक्षाओं को अपडेट करें
|
||||
मल्टी-टेबल स्थिरता के लिए परीक्षण जोड़ें
|
||||
क्वेरी योजनाओं में कोई ALLOW FILTERING न होने की पुष्टि करें
|
||||
|
||||
**`tests/unit/test_query/test_triples_cassandra_query.py`**
|
||||
प्रदर्शन दावों को अपडेट करें
|
||||
नए तालिकाओं के खिलाफ सभी 8 क्वेरी पैटर्न का परीक्षण करें
|
||||
सही तालिकाओं में क्वेरी रूटिंग की पुष्टि करें
|
||||
|
||||
#### एकीकरण परीक्षण
|
||||
**`tests/integration/test_cassandra_integration.py`**
|
||||
नए स्कीमा के साथ एंड-टू-एंड परीक्षण
|
||||
प्रदर्शन बेंचमार्किंग तुलना
|
||||
तालिकाओं में डेटा स्थिरता सत्यापन
|
||||
|
||||
**`tests/unit/test_storage/test_cassandra_config_integration.py`**
|
||||
स्कीमा सत्यापन परीक्षणों को अपडेट करें
|
||||
माइग्रेशन परिदृश्यों का परीक्षण करें
|
||||
|
||||
### कार्यान्वयन रणनीति
|
||||
|
||||
#### चरण 1: स्कीमा और कोर विधियाँ
|
||||
1. **`init()` विधि को फिर से लिखें** - एक के बजाय चार तालिकाओं का निर्माण करें
|
||||
2. **`insert()` विधि को फिर से लिखें** - सभी चार तालिकाओं में बैच राइट्स
|
||||
3. **तैयार कथनों को लागू करें** - इष्टतम प्रदर्शन के लिए
|
||||
4. **टेबल रूटिंग लॉजिक जोड़ें** - प्रश्नों को इष्टतम तालिकाओं पर निर्देशित करें
|
||||
5. **संग्रह हटाने को लागू करें** - triples_collection से पढ़ें, सभी तालिकाओं से बैच हटाएं
|
||||
|
||||
#### चरण 2: क्वेरी विधि अनुकूलन
|
||||
1. **प्रत्येक get_* विधि को फिर से लिखें** ताकि इष्टतम तालिका का उपयोग किया जा सके
|
||||
2. **सभी ALLOW FILTERING उपयोग को हटा दें**
|
||||
3. **कुशल क्लस्टरिंग कुंजी उपयोग को लागू करें**
|
||||
4. **क्वेरी प्रदर्शन लॉगिंग जोड़ें**
|
||||
|
||||
#### चरण 3: संग्रह प्रबंधन
|
||||
1. **`delete_collection()` को अपडेट करें** - सभी तीन तालिकाओं से हटाएं
|
||||
2. **संगति सत्यापन जोड़ें** - सुनिश्चित करें कि सभी तालिकाओं को सिंक में रखा जाए
|
||||
3. **बैच ऑपरेशंस लागू करें** - परमाणु मल्टी-टेबल ऑपरेशंस के लिए
|
||||
|
||||
### प्रमुख कार्यान्वयन विवरण
|
||||
|
||||
#### बैच राइट रणनीति
|
||||
```python
|
||||
def insert(self, collection, s, p, o):
|
||||
batch = BatchStatement()
|
||||
|
||||
# Insert into all four tables
|
||||
batch.add(self.insert_subject_stmt, (collection, s, p, o))
|
||||
batch.add(self.insert_po_stmt, (collection, p, o, s))
|
||||
batch.add(self.insert_object_stmt, (collection, o, s, p))
|
||||
batch.add(self.insert_collection_stmt, (collection, s, p, o))
|
||||
|
||||
self.session.execute(batch)
|
||||
```
|
||||
|
||||
#### प्रश्न रूटिंग लॉजिक (Query Routing Logic)
|
||||
```python
|
||||
def get_po(self, collection, p, o, limit=10):
|
||||
# Route to triples_p table - NO ALLOW FILTERING!
|
||||
return self.session.execute(
|
||||
self.get_po_stmt,
|
||||
(collection, p, o, limit)
|
||||
)
|
||||
|
||||
def get_spo(self, collection, s, p, o, limit=10):
|
||||
# Route to triples_collection table for exact SPO lookup
|
||||
return self.session.execute(
|
||||
self.get_spo_stmt,
|
||||
(collection, s, p, o, limit)
|
||||
)
|
||||
```
|
||||
|
||||
#### संग्रह हटाने का तर्क
|
||||
```python
|
||||
def delete_collection(self, collection):
|
||||
# Step 1: Read all triples from collection table
|
||||
rows = self.session.execute(
|
||||
f"SELECT s, p, o FROM {self.collection_table} WHERE collection = %s",
|
||||
(collection,)
|
||||
)
|
||||
|
||||
# Step 2: Batch delete from all 4 tables
|
||||
batch = BatchStatement()
|
||||
count = 0
|
||||
|
||||
for row in rows:
|
||||
s, p, o = row.s, row.p, row.o
|
||||
|
||||
# Delete using full partition keys for each table
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.subject_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.po_table} WHERE collection = ? AND p = ? AND o = ? AND s = ?"
|
||||
), (collection, p, o, s))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.object_table} WHERE collection = ? AND o = ? AND s = ? AND p = ?"
|
||||
), (collection, o, s, p))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.collection_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
count += 1
|
||||
|
||||
# Execute every 100 triples to avoid oversized batches
|
||||
if count % 100 == 0:
|
||||
self.session.execute(batch)
|
||||
batch = BatchStatement()
|
||||
|
||||
# Execute remaining deletions
|
||||
if count % 100 != 0:
|
||||
self.session.execute(batch)
|
||||
|
||||
logger.info(f"Deleted {count} triples from collection {collection}")
|
||||
```
|
||||
|
||||
#### तैयार स्टेटमेंट अनुकूलन (तैयार कथन अनुकूलन)
|
||||
```python
|
||||
def prepare_statements(self):
|
||||
# Cache prepared statements for better performance
|
||||
self.insert_subject_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.subject_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_po_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.po_table} (collection, p, o, s) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_object_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.object_table} (collection, o, s, p) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_collection_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.collection_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
# ... query statements
|
||||
```
|
||||
|
||||
## माइग्रेशन रणनीति
|
||||
|
||||
### डेटा माइग्रेशन दृष्टिकोण
|
||||
|
||||
#### विकल्प 1: ब्लू-ग्रीन परिनियोजन (अनुशंसित)
|
||||
1. **नए स्कीमा को मौजूदा स्कीमा के साथ तैनात करें** - अस्थायी रूप से अलग-अलग टेबल नामों का उपयोग करें
|
||||
2. **डबल-राइट अवधि** - संक्रमण के दौरान पुराने और नए दोनों स्कीमा में लिखें
|
||||
3. **बैकग्राउंड माइग्रेशन** - मौजूदा डेटा को नई तालिकाओं में कॉपी करें
|
||||
4. **रीड स्विच करें** - डेटा माइग्रेट होने के बाद प्रश्नों को नई तालिकाओं पर रूट करें
|
||||
5. **पुराने तालिकाओं को हटाएं** - सत्यापन अवधि के बाद
|
||||
|
||||
#### विकल्प 2: इन-प्लेस माइग्रेशन
|
||||
1. **स्कीमा जोड़ना** - मौजूदा कीस्पेस में नई तालिकाएँ बनाएँ
|
||||
2. **डेटा माइग्रेशन स्क्रिप्ट** - बैच कॉपी पुराने टेबल से नई तालिकाओं में
|
||||
3. **एप्लिकेशन अपडेट** - माइग्रेशन पूरा होने के बाद नया कोड तैनात करें
|
||||
4. **पुरानी टेबल की सफाई** - पुरानी टेबल और इंडेक्स हटाएं
|
||||
|
||||
### पश्चगामी अनुकूलता
|
||||
|
||||
#### परिनियोजन रणनीति
|
||||
```python
|
||||
# Environment variable to control table usage during migration
|
||||
USE_LEGACY_TABLES = os.getenv('CASSANDRA_USE_LEGACY', 'false').lower() == 'true'
|
||||
|
||||
class KnowledgeGraph:
|
||||
def __init__(self, ...):
|
||||
if USE_LEGACY_TABLES:
|
||||
self.init_legacy_schema()
|
||||
else:
|
||||
self.init_optimized_schema()
|
||||
```
|
||||
|
||||
#### माइग्रेशन स्क्रिप्ट
|
||||
```python
|
||||
def migrate_data():
|
||||
# Read from old table
|
||||
old_triples = session.execute("SELECT collection, s, p, o FROM triples")
|
||||
|
||||
# Batch write to new tables
|
||||
for batch in batched(old_triples, 100):
|
||||
batch_stmt = BatchStatement()
|
||||
for row in batch:
|
||||
# Add to all three new tables
|
||||
batch_stmt.add(insert_subject_stmt, row)
|
||||
batch_stmt.add(insert_po_stmt, (row.collection, row.p, row.o, row.s))
|
||||
batch_stmt.add(insert_object_stmt, (row.collection, row.o, row.s, row.p))
|
||||
session.execute(batch_stmt)
|
||||
```
|
||||
|
||||
### सत्यापन रणनीति
|
||||
|
||||
#### डेटा संगति जांच
|
||||
```python
|
||||
def validate_migration():
|
||||
# Count total records in old vs new tables
|
||||
old_count = session.execute("SELECT COUNT(*) FROM triples WHERE collection = ?", (collection,))
|
||||
new_count = session.execute("SELECT COUNT(*) FROM triples_by_subject WHERE collection = ?", (collection,))
|
||||
|
||||
assert old_count == new_count, f"Record count mismatch: {old_count} vs {new_count}"
|
||||
|
||||
# Spot check random samples
|
||||
sample_queries = generate_test_queries()
|
||||
for query in sample_queries:
|
||||
old_result = execute_legacy_query(query)
|
||||
new_result = execute_optimized_query(query)
|
||||
assert old_result == new_result, f"Query results differ for {query}"
|
||||
```
|
||||
|
||||
## परीक्षण रणनीति
|
||||
|
||||
### प्रदर्शन परीक्षण
|
||||
|
||||
#### बेंचमार्क परिदृश्य
|
||||
1. **क्वेरी प्रदर्शन तुलना**
|
||||
सभी 8 क्वेरी प्रकारों के लिए पूर्व/पश्च प्रदर्शन मेट्रिक्स
|
||||
`get_po` प्रदर्शन सुधार पर ध्यान केंद्रित करें (ALLOW FILTERING को हटाना)
|
||||
विभिन्न डेटा आकारों के तहत क्वेरी विलंबता को मापें
|
||||
|
||||
2. **लोड परीक्षण**
|
||||
समवर्ती क्वेरी निष्पादन
|
||||
बैच ऑपरेशनों के साथ लेखन थ्रूपुट
|
||||
मेमोरी और सीपीयू उपयोग
|
||||
|
||||
3. **स्केलेबिलिटी परीक्षण**
|
||||
बढ़ते संग्रह आकारों के साथ प्रदर्शन
|
||||
मल्टी-कलेक्शन क्वेरी वितरण
|
||||
क्लस्टर नोड उपयोग
|
||||
|
||||
#### परीक्षण डेटा सेट
|
||||
**छोटा:** प्रति संग्रह 10K त्रिगुण
|
||||
**मध्यम:** प्रति संग्रह 100K त्रिगुण
|
||||
**बड़ा:** 1M+ त्रिगुण
|
||||
**एकाधिक संग्रह:** परीक्षण विभाजन वितरण
|
||||
|
||||
### कार्यात्मक परीक्षण
|
||||
|
||||
#### यूनिट टेस्ट अपडेट
|
||||
```python
|
||||
# Example test structure for new implementation
|
||||
class TestCassandraKGPerformance:
|
||||
def test_get_po_no_allow_filtering(self):
|
||||
# Verify get_po queries don't use ALLOW FILTERING
|
||||
with patch('cassandra.cluster.Session.execute') as mock_execute:
|
||||
kg.get_po('test_collection', 'predicate', 'object')
|
||||
executed_query = mock_execute.call_args[0][0]
|
||||
assert 'ALLOW FILTERING' not in executed_query
|
||||
|
||||
def test_multi_table_consistency(self):
|
||||
# Verify all tables stay in sync
|
||||
kg.insert('test', 's1', 'p1', 'o1')
|
||||
|
||||
# Check all tables contain the triple
|
||||
assert_triple_exists('triples_by_subject', 'test', 's1', 'p1', 'o1')
|
||||
assert_triple_exists('triples_by_po', 'test', 'p1', 'o1', 's1')
|
||||
assert_triple_exists('triples_by_object', 'test', 'o1', 's1', 'p1')
|
||||
```
|
||||
|
||||
#### एकीकरण परीक्षण अपडेट
|
||||
```python
|
||||
class TestCassandraIntegration:
|
||||
def test_query_performance_regression(self):
|
||||
# Ensure new implementation is faster than old
|
||||
old_time = benchmark_legacy_get_po()
|
||||
new_time = benchmark_optimized_get_po()
|
||||
assert new_time < old_time * 0.5 # At least 50% improvement
|
||||
|
||||
def test_end_to_end_workflow(self):
|
||||
# Test complete write -> query -> delete cycle
|
||||
# Verify no performance degradation in integration
|
||||
```
|
||||
|
||||
### रोलबैक योजना
|
||||
|
||||
#### त्वरित रोलबैक रणनीति
|
||||
1. **पर्यावरण चर स्विच** - तुरंत पुराने तालिकाओं पर वापस स्विच करें
|
||||
2. **पुराने तालिकाओं को बनाए रखें** - प्रदर्शन साबित होने तक उन्हें हटाएं नहीं
|
||||
3. **निगरानी अलर्ट** - त्रुटि दर/विलंबता के आधार पर स्वचालित रोलबैक ट्रिगर
|
||||
|
||||
#### रोलबैक सत्यापन
|
||||
```python
|
||||
def rollback_to_legacy():
|
||||
# Set environment variable
|
||||
os.environ['CASSANDRA_USE_LEGACY'] = 'true'
|
||||
|
||||
# Restart services to pick up change
|
||||
restart_cassandra_services()
|
||||
|
||||
# Validate functionality
|
||||
run_smoke_tests()
|
||||
```
|
||||
|
||||
## जोखिम और विचार
|
||||
|
||||
### प्रदर्शन जोखिम
|
||||
**लेखन विलंबता में वृद्धि** - प्रति सम्मिलित 4x लेखन संचालन (3-तालिका दृष्टिकोण से 33% अधिक)
|
||||
**भंडारण ओवरहेड** - 4x भंडारण आवश्यकता (3-तालिका दृष्टिकोण से 33% अधिक)
|
||||
**बैच लेखन विफलताएं** - उचित त्रुटि प्रबंधन की आवश्यकता
|
||||
**हटाने की जटिलता** - संग्रह हटाने के लिए रीड-देन-डिलीट लूप की आवश्यकता होती है
|
||||
|
||||
### परिचालन जोखिम
|
||||
**स्थानांतरण जटिलता** - बड़े डेटासेट के लिए डेटा स्थानांतरण
|
||||
**संगति चुनौतियां** - यह सुनिश्चित करना कि सभी तालिकाएं सिंक्रनाइज़ रहें
|
||||
**निगरानी अंतराल** - मल्टी-टेबल ऑपरेशनों के लिए नए मेट्रिक्स की आवश्यकता
|
||||
|
||||
### शमन रणनीतियाँ
|
||||
1. **धीरे-धीरे रोलआउट** - छोटे संग्रहों से शुरुआत करें
|
||||
2. **व्यापक निगरानी** - सभी प्रदर्शन मेट्रिक्स को ट्रैक करें
|
||||
3. **स्वचालित सत्यापन** - निरंतर संगति जांच
|
||||
4. **त्वरित रोलबैक क्षमता** - पर्यावरण-आधारित तालिका चयन
|
||||
|
||||
## सफलता मानदंड
|
||||
|
||||
### प्रदर्शन सुधार
|
||||
[ ] **ALLOW FILTERING को समाप्त करें** - get_po और get_os क्वेरी फ़िल्टरिंग के बिना चलती हैं
|
||||
[ ] **क्वेरी विलंबता में कमी** - क्वेरी प्रतिक्रिया समय में 50%+ सुधार
|
||||
[ ] **बेहतर लोड वितरण** - कोई हॉट विभाजन नहीं, क्लस्टर नोड्स में समान लोड
|
||||
[ ] **स्केलेबल प्रदर्शन** - क्वेरी समय परिणाम आकार के समानुपाती, कुल डेटा के समानुपाती नहीं
|
||||
|
||||
### कार्यात्मक आवश्यकताएँ
|
||||
[ ] **एपीआई संगतता** - सभी मौजूदा कोड अपरिवर्तित रूप से काम करना जारी रखता है
|
||||
[ ] **डेटा संगति** - तीनों तालिकाओं को सिंक्रनाइज़ रखा जाता है
|
||||
[ ] **कोई डेटा हानि नहीं** - माइग्रेशन सभी मौजूदा त्रिगुणों को संरक्षित करता है
|
||||
[ ] **पिछड़ा संगतता** - विरासत स्कीमा पर वापस रोलबैक करने की क्षमता
|
||||
|
||||
### परिचालन आवश्यकताएँ
|
||||
[ ] **सुरक्षित स्थानांतरण** - रोलबैक क्षमता के साथ ब्लू-ग्रीन परिनियोजन
|
||||
[ ] **निगरानी कवरेज** - मल्टी-टेबल ऑपरेशनों के लिए व्यापक मेट्रिक्स
|
||||
[ ] **परीक्षण कवरेज** - सभी क्वेरी पैटर्न प्रदर्शन बेंचमार्क के साथ परीक्षण किए गए
|
||||
[ ] **प्रलेखन** - अद्यतन परिनियोजन और परिचालन प्रक्रियाएं
|
||||
|
||||
## समयरेखा
|
||||
|
||||
### चरण 1: कार्यान्वयन
|
||||
[ ] मल्टी-टेबल स्कीमा के साथ `cassandra_kg.py` को फिर से लिखें
|
||||
[ ] बैच लेखन संचालन लागू करें
|
||||
[ ] तैयार स्टेटमेंट अनुकूलन जोड़ें
|
||||
[ ] यूनिट परीक्षण अपडेट करें
|
||||
|
||||
### चरण 2: एकीकरण परीक्षण
|
||||
[ ] एकीकरण परीक्षण अपडेट करें
|
||||
[ ] प्रदर्शन बेंचमार्किंग
|
||||
[ ] यथार्थवादी डेटा वॉल्यूम के साथ लोड परीक्षण
|
||||
[ ] डेटा संगति के लिए सत्यापन स्क्रिप्ट
|
||||
|
||||
### चरण 3: माइग्रेशन योजना
|
||||
[ ] ब्लू-ग्रीन परिनियोजन स्क्रिप्ट
|
||||
[ ] डेटा माइग्रेशन उपकरण
|
||||
[ ] निगरानी डैशबोर्ड अपडेट
|
||||
[ ] रोलबैक प्रक्रियाएं
|
||||
|
||||
### चरण 4: उत्पादन परिनियोजन
|
||||
[ ] उत्पादन में क्रमिक रोलआउट
|
||||
[ ] प्रदर्शन निगरानी और सत्यापन
|
||||
[ ] विरासत तालिका सफाई
|
||||
[ ] प्रलेखन अपडेट
|
||||
|
||||
## निष्कर्ष
|
||||
|
||||
यह मल्टी-टेबल डीनॉर्मलाइज़ेशन रणनीति दो महत्वपूर्ण प्रदर्शन बाधाओं को सीधे संबोधित करती है:
|
||||
|
||||
1. **महंगे ALLOW FILTERING को समाप्त करता है** प्रत्येक क्वेरी पैटर्न के लिए इष्टतम तालिका संरचनाएं प्रदान करके
|
||||
2. **बेहतर क्लस्टरिंग प्रभावशीलता** समग्र विभाजन कुंजियों के माध्यम से जो लोड को ठीक से वितरित करते हैं
|
||||
|
||||
यह दृष्टिकोण कैसेंड्रा की ताकत का लाभ उठाता है जबकि पूर्ण एपीआई संगतता बनाए रखता है, यह सुनिश्चित करता है कि मौजूदा कोड प्रदर्शन सुधारों से स्वचालित रूप से लाभान्वित होता है।
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Tech Spec: Cassandra Knowledge Base Performance Refactor"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Tech Spec: Cassandra Knowledge Base Performance Refactor
|
||||
|
||||
**Status:** Draft
|
||||
|
|
|
|||
687
docs/tech-specs/cassandra-performance-refactor.pt.md
Normal file
687
docs/tech-specs/cassandra-performance-refactor.pt.md
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificação Técnica: Refatoração de Desempenho da Base de Conhecimento Cassandra"
|
||||
parent: "Portuguese (Beta)"
|
||||
---
|
||||
|
||||
# Especificação Técnica: Refatoração de Desempenho da Base de Conhecimento Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**Status:** Rascunho
|
||||
**Autor:** Assistente
|
||||
**Data:** 2025-09-18
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Esta especificação aborda problemas de desempenho na implementação da base de conhecimento Cassandra TrustGraph e propõe otimizações para o armazenamento e consulta de triplas RDF.
|
||||
|
||||
## Implementação Atual
|
||||
|
||||
### Design do Esquema
|
||||
|
||||
A implementação atual utiliza um design de tabela única em `trustgraph-flow/trustgraph/direct/cassandra_kg.py`:
|
||||
|
||||
```sql
|
||||
CREATE TABLE triples (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
|
||||
**Índices Secundários:**
|
||||
`triples_s` EM `s` (sujeito)
|
||||
`triples_p` EM `p` (predicado)
|
||||
`triples_o` EM `o` (objeto)
|
||||
|
||||
### Padrões de Consulta
|
||||
|
||||
A implementação atual suporta 8 padrões de consulta distintos:
|
||||
|
||||
1. **get_all(coleção, limite=50)** - Recupera todas as triplas para uma coleção
|
||||
```sql
|
||||
SELECT s, p, o FROM triples WHERE collection = ? LIMIT 50
|
||||
```
|
||||
|
||||
2. **get_s(collection, s, limit=10)** - Consulta por assunto
|
||||
```sql
|
||||
SELECT p, o FROM triples WHERE collection = ? AND s = ? LIMIT 10
|
||||
```
|
||||
|
||||
3. **get_p(collection, p, limit=10)** - Consulta por predicado
|
||||
```sql
|
||||
SELECT s, o FROM triples WHERE collection = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
4. **get_o(collection, o, limit=10)** - Consulta por objeto
|
||||
```sql
|
||||
SELECT s, p FROM triples WHERE collection = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
5. **get_sp(collection, s, p, limit=10)** - Consulta por sujeito + predicado
|
||||
```sql
|
||||
SELECT o FROM triples WHERE collection = ? AND s = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
6. **get_po(collection, p, o, limit=10)** - Consulta por predicado + objeto ⚠️
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
7. **get_os(collection, o, s, limit=10)** - Consulta por objeto + sujeito ⚠️
|
||||
```sql
|
||||
SELECT p FROM triples WHERE collection = ? AND o = ? AND s = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
8. **get_spo(collection, s, p, o, limit=10)** - Correspondência exata de tripla.
|
||||
```sql
|
||||
SELECT s as x FROM triples WHERE collection = ? AND s = ? AND p = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
### Arquitetura Atual
|
||||
|
||||
**Arquivo: `trustgraph-flow/trustgraph/direct/cassandra_kg.py`**
|
||||
Classe única `KnowledgeGraph` que gerencia todas as operações
|
||||
Pool de conexões através de uma lista global `_active_clusters`
|
||||
Nome de tabela fixo: `"triples"`
|
||||
Modelo de keyspace por usuário
|
||||
Replicação SimpleStrategy com fator 1
|
||||
|
||||
**Pontos de Integração:**
|
||||
**Caminho de Escrita:** `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
**Caminho de Consulta:** `trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
**Armazenamento de Conhecimento:** `trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
|
||||
## Problemas de Desempenho Identificados
|
||||
|
||||
### Problemas no Nível do Schema
|
||||
|
||||
1. **Design de Chave Primária Ineficiente**
|
||||
Atual: `PRIMARY KEY (collection, s, p, o)`
|
||||
Resulta em agrupamento inadequado para padrões de acesso comuns
|
||||
Força o uso de índices secundários caros
|
||||
|
||||
2. **Uso Excessivo de Índices Secundários** ⚠️
|
||||
Três índices secundários em colunas de alta cardinalidade (s, p, o)
|
||||
Índices secundários em Cassandra são caros e não escalam bem
|
||||
As consultas 6 e 7 requerem `ALLOW FILTERING`, indicando modelagem de dados inadequada
|
||||
|
||||
3. **Risco de Partições Quentes**
|
||||
Uma única chave de partição `collection` pode criar partições quentes
|
||||
Grandes coleções se concentrarão em nós únicos
|
||||
Não há estratégia de distribuição para balanceamento de carga
|
||||
|
||||
### Problemas no Nível da Consulta
|
||||
|
||||
1. **Uso de ALLOW FILTERING** ⚠️
|
||||
Dois tipos de consulta (get_po, get_os) requerem `ALLOW FILTERING`
|
||||
Essas consultas escaneiam várias partições e são extremamente caras
|
||||
O desempenho degrada linearmente com o tamanho dos dados
|
||||
|
||||
2. **Padrões de Acesso Ineficientes**
|
||||
Não há otimização para padrões de consulta RDF comuns
|
||||
Índices compostos ausentes para combinações de consulta frequentes
|
||||
Não há consideração para padrões de travessia de grafos
|
||||
|
||||
3. **Falta de Otimização de Consulta**
|
||||
Não há cache de prepared statements
|
||||
Não há dicas de consulta ou estratégias de otimização
|
||||
Não há consideração para paginação além de um simples LIMIT
|
||||
|
||||
## Declaração do Problema
|
||||
|
||||
A implementação atual da base de conhecimento Cassandra tem dois gargalos críticos de desempenho:
|
||||
|
||||
### 1. Desempenho Ineficiente da Consulta get_po
|
||||
|
||||
A consulta `get_po(collection, p, o)` é extremamente ineficiente devido à necessidade de `ALLOW FILTERING`:
|
||||
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
**Por que isso é problemático:**
|
||||
`ALLOW FILTERING` força o Cassandra a escanear todas as partições dentro da coleção.
|
||||
O desempenho diminui linearmente com o tamanho dos dados.
|
||||
Este é um padrão de consulta RDF comum (encontrar sujeitos que têm um relacionamento específico de predicado-objeto).
|
||||
Cria uma carga significativa no cluster à medida que os dados crescem.
|
||||
|
||||
### 2. Estratégia de Clustering Inadequada
|
||||
|
||||
A chave primária atual `PRIMARY KEY (collection, s, p, o)` oferece benefícios mínimos de clustering:
|
||||
|
||||
**Problemas com o clustering atual:**
|
||||
`collection` como chave de partição não distribui os dados de forma eficaz.
|
||||
A maioria das coleções contém dados diversos, tornando o clustering ineficaz.
|
||||
Não há consideração para padrões de acesso comuns em consultas RDF.
|
||||
Coleções grandes criam partições quentes em nós únicos.
|
||||
As colunas de clustering (s, p, o) não otimizam para padrões típicos de travessia de grafos.
|
||||
|
||||
**Impacto:**
|
||||
As consultas não se beneficiam da localidade dos dados.
|
||||
Utilização inadequada do cache.
|
||||
Distribuição desigual de carga entre os nós do cluster.
|
||||
Gargalos de escalabilidade à medida que as coleções crescem.
|
||||
|
||||
## Solução Proposta: Estratégia de Desnormalização de 4 Tabelas
|
||||
|
||||
### Visão Geral
|
||||
|
||||
Substitua a única tabela `triples` por quatro tabelas projetadas especificamente, cada uma otimizada para padrões de consulta específicos. Isso elimina a necessidade de índices secundários e ALLOW FILTERING, ao mesmo tempo em que fornece desempenho ideal para todos os tipos de consulta. A quarta tabela permite a exclusão eficiente de coleções, apesar das chaves de partição compostas.
|
||||
|
||||
### Novo Design de Esquema
|
||||
|
||||
**Tabela 1: Consultas Centradas no Sujeito (triples_s)**
|
||||
```sql
|
||||
CREATE TABLE triples_s (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY ((collection, s), p, o)
|
||||
);
|
||||
```
|
||||
**Otimiza:** get_s, get_sp, get_os
|
||||
**Chave de Partição:** (coleção, s) - Melhor distribuição do que apenas a coleção
|
||||
**Agrupamento:** (p, o) - Permite pesquisas eficientes de predicados/objetos para um sujeito
|
||||
|
||||
**Tabela 2: Consultas Predicado-Objeto (triples_p)**
|
||||
```sql
|
||||
CREATE TABLE triples_p (
|
||||
collection text,
|
||||
p text,
|
||||
o text,
|
||||
s text,
|
||||
PRIMARY KEY ((collection, p), o, s)
|
||||
);
|
||||
```
|
||||
**Otimiza:** get_p, get_po (elimina ALLOW FILTERING!)
|
||||
**Chave de Partição:** (coleção, p) - Acesso direto por predicado
|
||||
**Agrupamento:** (o, s) - Traversal eficiente de objeto-sujeito
|
||||
|
||||
**Tabela 3: Consultas Orientadas a Objetos (triples_o)**
|
||||
```sql
|
||||
CREATE TABLE triples_o (
|
||||
collection text,
|
||||
o text,
|
||||
s text,
|
||||
p text,
|
||||
PRIMARY KEY ((collection, o), s, p)
|
||||
);
|
||||
```
|
||||
**Otimiza:** get_o
|
||||
**Chave de Partição:** (coleção, o) - Acesso direto por objeto
|
||||
**Agrupamento:** (s, p) - Traversal eficiente de sujeito-predicado
|
||||
|
||||
**Tabela 4: Gerenciamento de Coleções e Consultas SPO (triples_collection)**
|
||||
```sql
|
||||
CREATE TABLE triples_collection (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
**Otimiza:** get_spo, delete_collection
|
||||
**Chave de Partição:** coleção apenas - Permite operações eficientes no nível da coleção.
|
||||
**Agrupamento:** (s, p, o) - Ordenação padrão de triplas.
|
||||
**Propósito:** Uso duplo para pesquisas exatas de SPO e como índice de exclusão.
|
||||
|
||||
### Mapeamento de Consultas
|
||||
|
||||
| Consulta Original | Tabela de Destino | Melhoria de Desempenho |
|
||||
|----------------|-------------|------------------------|
|
||||
| get_all(collection) | triples_s | PERMITE FILTRAGEM (aceitável para varredura) |
|
||||
| get_s(collection, s) | triples_s | Acesso direto à partição |
|
||||
| get_p(collection, p) | triples_p | Acesso direto à partição |
|
||||
| get_o(collection, o) | triples_o | Acesso direto à partição |
|
||||
| get_sp(collection, s, p) | triples_s | Partição + agrupamento |
|
||||
| get_po(collection, p, o) | triples_p | **Não mais PERMITE FILTRAGEM!** |
|
||||
| get_os(collection, o, s) | triples_o | Partição + agrupamento |
|
||||
| get_spo(collection, s, p, o) | triples_collection | Pesquisa de chave exata |
|
||||
| delete_collection(collection) | triples_collection | Lê o índice, exclusão em lote de todos |
|
||||
|
||||
### Estratégia de Exclusão de Coleção
|
||||
|
||||
Com chaves de partição compostas, não podemos simplesmente executar `DELETE FROM table WHERE collection = ?`. Em vez disso:
|
||||
|
||||
1. **Fase de Leitura:** Consulta `triples_collection` para enumerar todas as triplas:
|
||||
```sql
|
||||
SELECT s, p, o FROM triples_collection WHERE collection = ?
|
||||
```
|
||||
Isso é eficiente, já que `collection` é a chave de partição para esta tabela.
|
||||
|
||||
2. **Fase de Exclusão:** Para cada tripla (s, p, o), exclua de todas as 4 tabelas usando as chaves de partição completas:
|
||||
```sql
|
||||
DELETE FROM triples_s WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
DELETE FROM triples_p WHERE collection = ? AND p = ? AND o = ? AND s = ?
|
||||
DELETE FROM triples_o WHERE collection = ? AND o = ? AND s = ? AND p = ?
|
||||
DELETE FROM triples_collection WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
```
|
||||
Agrupado em lotes de 100 para maior eficiência.
|
||||
|
||||
**Análise de Compromissos:**
|
||||
✅ Mantém o desempenho ideal das consultas com partições distribuídas.
|
||||
✅ Sem partições com alta carga para grandes coleções.
|
||||
❌ Lógica de exclusão mais complexa (leitura e depois exclusão).
|
||||
❌ Tempo de exclusão proporcional ao tamanho da coleção.
|
||||
|
||||
### Benefícios
|
||||
|
||||
1. **Elimina ALLOW FILTERING** - Cada consulta tem um caminho de acesso ideal (exceto a varredura get_all).
|
||||
2. **Sem Índices Secundários** - Cada tabela É o índice para seu padrão de consulta.
|
||||
3. **Melhor Distribuição de Dados** - As chaves de partição compostas distribuem a carga de forma eficaz.
|
||||
4. **Desempenho Previsível** - O tempo de consulta é proporcional ao tamanho do resultado, não ao tamanho total dos dados.
|
||||
5. **Aproveita os Pontos Fortes do Cassandra** - Projetado para a arquitetura do Cassandra.
|
||||
6. **Permite a Exclusão de Coleções** - triples_collection serve como índice de exclusão.
|
||||
|
||||
## Plano de Implementação
|
||||
|
||||
### Arquivos que Requerem Alterações
|
||||
|
||||
#### Arquivo de Implementação Primário
|
||||
|
||||
**`trustgraph-flow/trustgraph/direct/cassandra_kg.py`** - Reescrita completa necessária.
|
||||
|
||||
**Métodos Atuais a Serem Refatorados:**
|
||||
```python
|
||||
# Schema initialization
|
||||
def init(self) -> None # Replace single table with three tables
|
||||
|
||||
# Insert operations
|
||||
def insert(self, collection, s, p, o) -> None # Write to all three tables
|
||||
|
||||
# Query operations (API unchanged, implementation optimized)
|
||||
def get_all(self, collection, limit=50) # Use triples_by_subject
|
||||
def get_s(self, collection, s, limit=10) # Use triples_by_subject
|
||||
def get_p(self, collection, p, limit=10) # Use triples_by_po
|
||||
def get_o(self, collection, o, limit=10) # Use triples_by_object
|
||||
def get_sp(self, collection, s, p, limit=10) # Use triples_by_subject
|
||||
def get_po(self, collection, p, o, limit=10) # Use triples_by_po (NO ALLOW FILTERING!)
|
||||
def get_os(self, collection, o, s, limit=10) # Use triples_by_subject
|
||||
def get_spo(self, collection, s, p, o, limit=10) # Use triples_by_subject
|
||||
|
||||
# Collection management
|
||||
def delete_collection(self, collection) -> None # Delete from all three tables
|
||||
```
|
||||
|
||||
#### Arquivos de Integração (Nenhuma Alteração de Lógica Necessária)
|
||||
|
||||
**`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`**
|
||||
Nenhuma alteração necessária - utiliza a API KnowledgeGraph existente
|
||||
Beneficia automaticamente das melhorias de desempenho
|
||||
|
||||
**`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`**
|
||||
Nenhuma alteração necessária - utiliza a API KnowledgeGraph existente
|
||||
Beneficia automaticamente das melhorias de desempenho
|
||||
|
||||
### Arquivos de Teste que Requerem Atualizações
|
||||
|
||||
#### Testes Unitários
|
||||
**`tests/unit/test_storage/test_triples_cassandra_storage.py`**
|
||||
Atualizar as expectativas dos testes para as alterações no esquema
|
||||
Adicionar testes para a consistência de várias tabelas
|
||||
Verificar se não há ALLOW FILTERING nos planos de consulta
|
||||
|
||||
**`tests/unit/test_query/test_triples_cassandra_query.py`**
|
||||
Atualizar as asserções de desempenho
|
||||
Testar todos os 8 padrões de consulta contra as novas tabelas
|
||||
Verificar o roteamento da consulta para as tabelas corretas
|
||||
|
||||
#### Testes de Integração
|
||||
**`tests/integration/test_cassandra_integration.py`**
|
||||
Testes de ponta a ponta com o novo esquema
|
||||
Comparativos de benchmarking de desempenho
|
||||
Verificação da consistência dos dados entre as tabelas
|
||||
|
||||
**`tests/unit/test_storage/test_cassandra_config_integration.py`**
|
||||
Atualizar os testes de validação de esquema
|
||||
Testar cenários de migração
|
||||
|
||||
### Estratégia de Implementação
|
||||
|
||||
#### Fase 1: Esquema e Métodos Principais
|
||||
1. **Reescrever o método `init()`** - Criar quatro tabelas em vez de uma
|
||||
2. **Reescrever o método `insert()`** - Gravações em lote em todas as quatro tabelas
|
||||
3. **Implementar instruções preparadas** - Para desempenho ideal
|
||||
4. **Adicionar lógica de roteamento de tabela** - Direcionar consultas para as tabelas mais adequadas
|
||||
5. **Implementar a exclusão de coleções** - Ler de triples_collection, excluir em lote de todas as tabelas
|
||||
|
||||
#### Fase 2: Otimização do Método de Consulta
|
||||
1. **Reescrever cada método get_*** para usar a tabela mais adequada
|
||||
2. **Remover todo o uso de ALLOW FILTERING**
|
||||
3. **Implementar o uso eficiente da chave de agrupamento**
|
||||
4. **Adicionar registro de desempenho da consulta**
|
||||
|
||||
#### Fase 3: Gerenciamento de Coleções
|
||||
1. **Atualizar `delete_collection()`** - Remover de todas as três tabelas
|
||||
2. **Adicionar verificação de consistência** - Garantir que todas as tabelas permaneçam sincronizadas
|
||||
3. **Implementar operações em lote** - Para operações multi-tabela atômicas
|
||||
|
||||
### Detalhes Chave da Implementação
|
||||
|
||||
#### Estratégia de Gravação em Lote
|
||||
```python
|
||||
def insert(self, collection, s, p, o):
|
||||
batch = BatchStatement()
|
||||
|
||||
# Insert into all four tables
|
||||
batch.add(self.insert_subject_stmt, (collection, s, p, o))
|
||||
batch.add(self.insert_po_stmt, (collection, p, o, s))
|
||||
batch.add(self.insert_object_stmt, (collection, o, s, p))
|
||||
batch.add(self.insert_collection_stmt, (collection, s, p, o))
|
||||
|
||||
self.session.execute(batch)
|
||||
```
|
||||
|
||||
#### Lógica de Roteamento de Consultas
|
||||
```python
|
||||
def get_po(self, collection, p, o, limit=10):
|
||||
# Route to triples_p table - NO ALLOW FILTERING!
|
||||
return self.session.execute(
|
||||
self.get_po_stmt,
|
||||
(collection, p, o, limit)
|
||||
)
|
||||
|
||||
def get_spo(self, collection, s, p, o, limit=10):
|
||||
# Route to triples_collection table for exact SPO lookup
|
||||
return self.session.execute(
|
||||
self.get_spo_stmt,
|
||||
(collection, s, p, o, limit)
|
||||
)
|
||||
```
|
||||
|
||||
#### Lógica de Exclusão de Coleções
|
||||
```python
|
||||
def delete_collection(self, collection):
|
||||
# Step 1: Read all triples from collection table
|
||||
rows = self.session.execute(
|
||||
f"SELECT s, p, o FROM {self.collection_table} WHERE collection = %s",
|
||||
(collection,)
|
||||
)
|
||||
|
||||
# Step 2: Batch delete from all 4 tables
|
||||
batch = BatchStatement()
|
||||
count = 0
|
||||
|
||||
for row in rows:
|
||||
s, p, o = row.s, row.p, row.o
|
||||
|
||||
# Delete using full partition keys for each table
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.subject_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.po_table} WHERE collection = ? AND p = ? AND o = ? AND s = ?"
|
||||
), (collection, p, o, s))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.object_table} WHERE collection = ? AND o = ? AND s = ? AND p = ?"
|
||||
), (collection, o, s, p))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.collection_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
count += 1
|
||||
|
||||
# Execute every 100 triples to avoid oversized batches
|
||||
if count % 100 == 0:
|
||||
self.session.execute(batch)
|
||||
batch = BatchStatement()
|
||||
|
||||
# Execute remaining deletions
|
||||
if count % 100 != 0:
|
||||
self.session.execute(batch)
|
||||
|
||||
logger.info(f"Deleted {count} triples from collection {collection}")
|
||||
```
|
||||
|
||||
#### Otimização de Instruções Preparadas
|
||||
```python
|
||||
def prepare_statements(self):
|
||||
# Cache prepared statements for better performance
|
||||
self.insert_subject_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.subject_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_po_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.po_table} (collection, p, o, s) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_object_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.object_table} (collection, o, s, p) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_collection_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.collection_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
# ... query statements
|
||||
```
|
||||
|
||||
## Estratégia de Migração
|
||||
|
||||
### Abordagem de Migração de Dados
|
||||
|
||||
#### Opção 1: Implantação Blue-Green (Recomendada)
|
||||
1. **Implantar o novo esquema junto com o existente** - Use nomes de tabelas diferentes temporariamente
|
||||
2. **Período de escrita dupla** - Escrever tanto no esquema antigo quanto no novo durante a transição
|
||||
3. **Migração em segundo plano** - Copiar dados existentes para novas tabelas
|
||||
4. **Alternar leituras** - Direcionar consultas para novas tabelas assim que os dados forem migrados
|
||||
5. **Remover tabelas antigas** - Após o período de verificação
|
||||
|
||||
#### Opção 2: Migração no Local
|
||||
1. **Adição de esquema** - Criar novas tabelas no keyspace existente
|
||||
2. **Script de migração de dados** - Copiar em lote da tabela antiga para as novas tabelas
|
||||
3. **Atualização do aplicativo** - Implantar novo código após a conclusão da migração
|
||||
4. **Limpeza da tabela antiga** - Remover a tabela antiga e os índices
|
||||
|
||||
### Compatibilidade com Versões Anteriores
|
||||
|
||||
#### Estratégia de Implantação
|
||||
```python
|
||||
# Environment variable to control table usage during migration
|
||||
USE_LEGACY_TABLES = os.getenv('CASSANDRA_USE_LEGACY', 'false').lower() == 'true'
|
||||
|
||||
class KnowledgeGraph:
|
||||
def __init__(self, ...):
|
||||
if USE_LEGACY_TABLES:
|
||||
self.init_legacy_schema()
|
||||
else:
|
||||
self.init_optimized_schema()
|
||||
```
|
||||
|
||||
#### Script de Migração
|
||||
```python
|
||||
def migrate_data():
|
||||
# Read from old table
|
||||
old_triples = session.execute("SELECT collection, s, p, o FROM triples")
|
||||
|
||||
# Batch write to new tables
|
||||
for batch in batched(old_triples, 100):
|
||||
batch_stmt = BatchStatement()
|
||||
for row in batch:
|
||||
# Add to all three new tables
|
||||
batch_stmt.add(insert_subject_stmt, row)
|
||||
batch_stmt.add(insert_po_stmt, (row.collection, row.p, row.o, row.s))
|
||||
batch_stmt.add(insert_object_stmt, (row.collection, row.o, row.s, row.p))
|
||||
session.execute(batch_stmt)
|
||||
```
|
||||
|
||||
### Estratégia de Validação
|
||||
|
||||
#### Verificações de Consistência de Dados
|
||||
```python
|
||||
def validate_migration():
|
||||
# Count total records in old vs new tables
|
||||
old_count = session.execute("SELECT COUNT(*) FROM triples WHERE collection = ?", (collection,))
|
||||
new_count = session.execute("SELECT COUNT(*) FROM triples_by_subject WHERE collection = ?", (collection,))
|
||||
|
||||
assert old_count == new_count, f"Record count mismatch: {old_count} vs {new_count}"
|
||||
|
||||
# Spot check random samples
|
||||
sample_queries = generate_test_queries()
|
||||
for query in sample_queries:
|
||||
old_result = execute_legacy_query(query)
|
||||
new_result = execute_optimized_query(query)
|
||||
assert old_result == new_result, f"Query results differ for {query}"
|
||||
```
|
||||
|
||||
## Estratégia de Testes
|
||||
|
||||
### Testes de Desempenho
|
||||
|
||||
#### Cenários de Benchmark
|
||||
1. **Comparação de Desempenho de Consultas**
|
||||
Métricas de desempenho antes/depois para todos os 8 tipos de consulta
|
||||
Foco na melhoria de desempenho de `get_po` (eliminar `ALLOW FILTERING`)
|
||||
Medir a latência da consulta sob vários tamanhos de dados
|
||||
|
||||
2. **Testes de Carga**
|
||||
Execução de consultas concorrentes
|
||||
Taxa de transferência de escrita com operações em lote
|
||||
Utilização de memória e CPU
|
||||
|
||||
3. **Testes de Escalabilidade**
|
||||
Desempenho com tamanhos de coleção crescentes
|
||||
Distribuição de consultas em várias coleções
|
||||
Utilização de nós do cluster
|
||||
|
||||
#### Conjuntos de Dados de Teste
|
||||
**Pequeno:** 10K triplas por coleção
|
||||
**Médio:** 100K triplas por coleção
|
||||
**Grande:** 1M+ triplas por coleção
|
||||
**Múltiplas coleções:** Testar a distribuição de partições
|
||||
|
||||
### Testes Funcionais
|
||||
|
||||
#### Atualizações de Testes Unitários
|
||||
```python
|
||||
# Example test structure for new implementation
|
||||
class TestCassandraKGPerformance:
|
||||
def test_get_po_no_allow_filtering(self):
|
||||
# Verify get_po queries don't use ALLOW FILTERING
|
||||
with patch('cassandra.cluster.Session.execute') as mock_execute:
|
||||
kg.get_po('test_collection', 'predicate', 'object')
|
||||
executed_query = mock_execute.call_args[0][0]
|
||||
assert 'ALLOW FILTERING' not in executed_query
|
||||
|
||||
def test_multi_table_consistency(self):
|
||||
# Verify all tables stay in sync
|
||||
kg.insert('test', 's1', 'p1', 'o1')
|
||||
|
||||
# Check all tables contain the triple
|
||||
assert_triple_exists('triples_by_subject', 'test', 's1', 'p1', 'o1')
|
||||
assert_triple_exists('triples_by_po', 'test', 'p1', 'o1', 's1')
|
||||
assert_triple_exists('triples_by_object', 'test', 'o1', 's1', 'p1')
|
||||
```
|
||||
|
||||
#### Atualizações do Teste de Integração
|
||||
```python
|
||||
class TestCassandraIntegration:
|
||||
def test_query_performance_regression(self):
|
||||
# Ensure new implementation is faster than old
|
||||
old_time = benchmark_legacy_get_po()
|
||||
new_time = benchmark_optimized_get_po()
|
||||
assert new_time < old_time * 0.5 # At least 50% improvement
|
||||
|
||||
def test_end_to_end_workflow(self):
|
||||
# Test complete write -> query -> delete cycle
|
||||
# Verify no performance degradation in integration
|
||||
```
|
||||
|
||||
### Plano de Reversão
|
||||
|
||||
#### Estratégia de Reversão Rápida
|
||||
1. **Alternância de variáveis de ambiente** - Retorne imediatamente para as tabelas legadas.
|
||||
2. **Mantenha as tabelas legadas** - Não as exclua até que o desempenho seja comprovado.
|
||||
3. **Alertas de monitoramento** - Disparos de reversão automatizados com base em taxas de erro/latência.
|
||||
|
||||
#### Validação da Reversão
|
||||
```python
|
||||
def rollback_to_legacy():
|
||||
# Set environment variable
|
||||
os.environ['CASSANDRA_USE_LEGACY'] = 'true'
|
||||
|
||||
# Restart services to pick up change
|
||||
restart_cassandra_services()
|
||||
|
||||
# Validate functionality
|
||||
run_smoke_tests()
|
||||
```
|
||||
|
||||
## Riscos e Considerações
|
||||
|
||||
### Riscos de Desempenho
|
||||
**Aumento da latência de escrita** - 4 operações de escrita por inserção (33% a mais do que a abordagem de 3 tabelas)
|
||||
**Sobrecarga de armazenamento** - 4x o requisito de armazenamento (33% a mais do que a abordagem de 3 tabelas)
|
||||
**Falhas de escrita em lote** - Necessidade de tratamento adequado de erros
|
||||
**Complexidade da exclusão** - A exclusão da coleção requer um loop de leitura e exclusão
|
||||
|
||||
### Riscos Operacionais
|
||||
**Complexidade da migração** - Migração de dados para grandes conjuntos de dados
|
||||
**Desafios de consistência** - Garantir que todas as tabelas permaneçam sincronizadas
|
||||
**Lacunas de monitoramento** - Necessidade de novas métricas para operações de várias tabelas
|
||||
|
||||
### Estratégias de Mitigação
|
||||
1. **Implantação gradual** - Começar com pequenas coleções
|
||||
2. **Monitoramento abrangente** - Rastrear todas as métricas de desempenho
|
||||
3. **Validação automatizada** - Verificação contínua de consistência
|
||||
4. **Capacidade de reversão rápida** - Seleção de tabela baseada no ambiente
|
||||
|
||||
## Critérios de Sucesso
|
||||
|
||||
### Melhorias de Desempenho
|
||||
[ ] **Eliminar ALLOW FILTERING** - as consultas get_po e get_os são executadas sem filtragem
|
||||
[ ] **Redução da latência da consulta** - melhoria de 50% ou mais nos tempos de resposta da consulta
|
||||
[ ] **Melhor distribuição de carga** - Sem partições quentes, distribuição uniforme entre os nós do cluster
|
||||
[ ] **Desempenho escalável** - Tempo de consulta proporcional ao tamanho do resultado, não ao volume total de dados
|
||||
|
||||
### Requisitos Funcionais
|
||||
[ ] **Compatibilidade da API** - Todo o código existente continua a funcionar sem alterações
|
||||
[ ] **Consistência de dados** - As três tabelas permanecem sincronizadas
|
||||
[ ] **Nenhuma perda de dados** - A migração preserva todas as triplas existentes
|
||||
[ ] **Compatibilidade com versões anteriores** - Capacidade de reverter para o esquema legado
|
||||
|
||||
### Requisitos Operacionais
|
||||
[ ] **Migração segura** - Implantação blue-green com capacidade de reversão
|
||||
[ ] **Cobertura de monitoramento** - Métricas abrangentes para operações de várias tabelas
|
||||
[ ] **Cobertura de teste** - Todos os padrões de consulta testados com benchmarks de desempenho
|
||||
[ ] **Documentação** - Procedimentos de implantação e operação atualizados
|
||||
|
||||
## Cronograma
|
||||
|
||||
### Fase 1: Implementação
|
||||
[ ] Reescrever `cassandra_kg.py` com o esquema de várias tabelas
|
||||
[ ] Implementar operações de escrita em lote
|
||||
[ ] Adicionar otimização de declaração preparada
|
||||
[ ] Atualizar testes unitários
|
||||
|
||||
### Fase 2: Testes de Integração
|
||||
[ ] Atualizar testes de integração
|
||||
[ ] Benchmarking de desempenho
|
||||
[ ] Teste de carga com volumes de dados realistas
|
||||
[ ] Scripts de validação para consistência de dados
|
||||
|
||||
### Fase 3: Planejamento da Migração
|
||||
[ ] Scripts de implantação blue-green
|
||||
[ ] Ferramentas de migração de dados
|
||||
[ ] Atualizações do painel de monitoramento
|
||||
[ ] Procedimentos de reversão
|
||||
|
||||
### Fase 4: Implantação em Produção
|
||||
[ ] Implantação gradual em produção
|
||||
[ ] Monitoramento e validação de desempenho
|
||||
[ ] Limpeza de tabelas legadas
|
||||
[ ] Atualizações de documentação
|
||||
|
||||
## Conclusão
|
||||
|
||||
Esta estratégia de desnormalização multi-tabela aborda diretamente os dois gargalos de desempenho críticos:
|
||||
|
||||
1. **Elimina o ALLOW FILTERING caro** fornecendo estruturas de tabela ideais para cada padrão de consulta
|
||||
2. **Melhora a eficácia do agrupamento** por meio de chaves de partição compostas que distribuem a carga adequadamente
|
||||
|
||||
A abordagem aproveita os pontos fortes do Cassandra, mantendo a compatibilidade total da API, garantindo que o código existente se beneficie automaticamente das melhorias de desempenho.
|
||||
687
docs/tech-specs/cassandra-performance-refactor.ru.md
Normal file
687
docs/tech-specs/cassandra-performance-refactor.ru.md
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Технические спецификации: Оптимизация производительности базы знаний Cassandra"
|
||||
parent: "Russian (Beta)"
|
||||
---
|
||||
|
||||
# Технические спецификации: Оптимизация производительности базы знаний Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**Статус:** Черновик
|
||||
**Автор:** Ассистент
|
||||
**Дата:** 2025-09-18
|
||||
|
||||
## Обзор
|
||||
|
||||
Данная спецификация рассматривает проблемы производительности в реализации базы знаний TrustGraph на Cassandra и предлагает оптимизации для хранения и запросов RDF-тройных.
|
||||
|
||||
## Текущая реализация
|
||||
|
||||
### Структура данных
|
||||
|
||||
Текущая реализация использует структуру данных с одной таблицей в `trustgraph-flow/trustgraph/direct/cassandra_kg.py`:
|
||||
|
||||
```sql
|
||||
CREATE TABLE triples (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
|
||||
**Вторичные индексы:**
|
||||
`triples_s` по `s` (субъект)
|
||||
`triples_p` по `p` (предикат)
|
||||
`triples_o` по `o` (объект)
|
||||
|
||||
### Шаблоны запросов
|
||||
|
||||
Текущая реализация поддерживает 8 различных шаблонов запросов:
|
||||
|
||||
1. **get_all(collection, limit=50)** - Получить все тройки для коллекции
|
||||
```sql
|
||||
SELECT s, p, o FROM triples WHERE collection = ? LIMIT 50
|
||||
```
|
||||
|
||||
2. **get_s(collection, s, limit=10)** - Запрос по теме.
|
||||
```sql
|
||||
SELECT p, o FROM triples WHERE collection = ? AND s = ? LIMIT 10
|
||||
```
|
||||
|
||||
3. **get_p(collection, p, limit=10)** - Запрос по предикату.
|
||||
```sql
|
||||
SELECT s, o FROM triples WHERE collection = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
4. **get_o(collection, o, limit=10)** - Запрос по объекту.
|
||||
```sql
|
||||
SELECT s, p FROM triples WHERE collection = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
5. **get_sp(collection, s, p, limit=10)** - Запрос по субъекту + предикату.
|
||||
```sql
|
||||
SELECT o FROM triples WHERE collection = ? AND s = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
6. **get_po(collection, p, o, limit=10)** - Запрос по предикату + объекту ⚠️
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
7. **get_os(collection, o, s, limit=10)** - Запрос по объекту + субъекту ⚠️
|
||||
```sql
|
||||
SELECT p FROM triples WHERE collection = ? AND o = ? AND s = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
8. **get_spo(collection, s, p, o, limit=10)** - Точное соответствие тройке.
|
||||
```sql
|
||||
SELECT s as x FROM triples WHERE collection = ? AND s = ? AND p = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
### Текущая архитектура
|
||||
|
||||
**Файл: `trustgraph-flow/trustgraph/direct/cassandra_kg.py`**
|
||||
Один класс `KnowledgeGraph`, обрабатывающий все операции
|
||||
Объединение подключений через глобальный список `_active_clusters`
|
||||
Фиксированное имя таблицы: `"triples"`
|
||||
Пространство ключей для каждой модели пользователя
|
||||
Репликация SimpleStrategy с коэффициентом 1
|
||||
|
||||
**Точки интеграции:**
|
||||
**Путь записи:** `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
**Путь запроса:** `trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
**Хранилище знаний:** `trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
|
||||
## Выявленные проблемы с производительностью
|
||||
|
||||
### Проблемы на уровне схемы
|
||||
|
||||
1. **Неэффективный дизайн первичного ключа**
|
||||
Текущий: `PRIMARY KEY (collection, s, p, o)`
|
||||
Приводит к плохой кластеризации для распространенных шаблонов доступа
|
||||
Заставляет использовать дорогостоящие вторичные индексы
|
||||
|
||||
2. **Чрезмерное использование вторичных индексов** ⚠️
|
||||
Три вторичных индекса на столбцах с высокой кардинальностью (s, p, o)
|
||||
Вторичные индексы в Cassandra дороги и плохо масштабируются
|
||||
Запросы 6 и 7 требуют `ALLOW FILTERING`, что указывает на плохое моделирование данных
|
||||
|
||||
3. **Риск "горячих" разделов**
|
||||
Один ключ раздела `collection` может создавать "горячие" разделы
|
||||
Большие коллекции будут концентрироваться на отдельных узлах
|
||||
Отсутствует стратегия распределения для балансировки нагрузки
|
||||
|
||||
### Проблемы на уровне запросов
|
||||
|
||||
1. **Использование ALLOW FILTERING** ⚠️
|
||||
Два типа запросов (get_po, get_os) требуют `ALLOW FILTERING`
|
||||
Эти запросы сканируют несколько разделов и чрезвычайно дороги
|
||||
Производительность ухудшается линейно с увеличением объема данных
|
||||
|
||||
2. **Неэффективные шаблоны доступа**
|
||||
Отсутствует оптимизация для распространенных шаблонов запросов RDF
|
||||
Отсутствуют составные индексы для часто используемых комбинаций запросов
|
||||
Не учитываются шаблоны обхода графов
|
||||
|
||||
3. **Отсутствие оптимизации запросов**
|
||||
Отсутствует кэширование подготовленных выражений
|
||||
Отсутствуют подсказки или стратегии оптимизации запросов
|
||||
Не учитывается постраничная навигация, кроме простого LIMIT
|
||||
|
||||
## Описание проблемы
|
||||
|
||||
Текущая реализация базы знаний Cassandra имеет два критических узких места в производительности:
|
||||
|
||||
### 1. Неэффективная производительность запроса get_po
|
||||
|
||||
Запрос `get_po(collection, p, o)` крайне неэффективен, поскольку требует `ALLOW FILTERING`:
|
||||
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
**Почему это является проблемой:**
|
||||
`ALLOW FILTERING` заставляет Cassandra сканировать все разделы внутри коллекции.
|
||||
Производительность ухудшается линейно с увеличением размера данных.
|
||||
Это распространенный шаблон запросов RDF (поиск объектов, имеющих определенную связь "субъект-предикат-объект").
|
||||
Это создает значительную нагрузку на кластер по мере роста данных.
|
||||
|
||||
### 2. Неоптимальная стратегия кластеризации
|
||||
|
||||
Текущий первичный ключ `PRIMARY KEY (collection, s, p, o)` обеспечивает минимальные преимущества кластеризации:
|
||||
|
||||
**Проблемы с текущей кластеризацией:**
|
||||
`collection` в качестве ключа раздела не обеспечивает эффективное распределение данных.
|
||||
Большинство коллекций содержат разнообразные данные, что делает кластеризацию неэффективной.
|
||||
Отсутствует учет типичных шаблонов доступа в запросах RDF.
|
||||
Большие коллекции создают "горячие" разделы на отдельных узлах.
|
||||
Столбцы кластеризации (s, p, o) не оптимизированы для типичных шаблонов обхода графа.
|
||||
|
||||
**Влияние:**
|
||||
Запросы не получают выгоды от локальности данных.
|
||||
Плохое использование кэша.
|
||||
Неравномерное распределение нагрузки между узлами кластера.
|
||||
"Узкие места" масштабируемости по мере роста коллекций.
|
||||
|
||||
## Предлагаемое решение: Стратегия денормализации с использованием 4 таблиц
|
||||
|
||||
### Обзор
|
||||
|
||||
Замените одну таблицу `triples` на четыре специализированные таблицы, каждая из которых оптимизирована для конкретных шаблонов запросов. Это устраняет необходимость во вторичных индексах и использовании ALLOW FILTERING, обеспечивая при этом оптимальную производительность для всех типов запросов. Четвертая таблица обеспечивает эффективное удаление коллекций, несмотря на составные ключи разделов.
|
||||
|
||||
### Новая структура схемы
|
||||
|
||||
**Таблица 1: Запросы, ориентированные на субъекты (triples_s)**
|
||||
```sql
|
||||
CREATE TABLE triples_s (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY ((collection, s), p, o)
|
||||
);
|
||||
```
|
||||
**Оптимизирует:** get_s, get_sp, get_os
|
||||
**Ключ разделения:** (collection, s) - Обеспечивает лучшую распределенность, чем только collection.
|
||||
**Кластеризация:** (p, o) - Обеспечивает эффективный поиск по предикатам/объектам для субъекта.
|
||||
|
||||
**Таблица 2: Запросы предикат-объект (triples_p)**
|
||||
```sql
|
||||
CREATE TABLE triples_p (
|
||||
collection text,
|
||||
p text,
|
||||
o text,
|
||||
s text,
|
||||
PRIMARY KEY ((collection, p), o, s)
|
||||
);
|
||||
```
|
||||
**Оптимизирует:** get_p, get_po (исключает ALLOW FILTERING!)
|
||||
**Ключ партиции:** (collection, p) - Прямой доступ по предикату
|
||||
**Кластеризация:** (o, s) - Эффективный обход объектов и субъектов
|
||||
|
||||
**Таблица 3: Объектно-ориентированные запросы (triples_o)**
|
||||
```sql
|
||||
CREATE TABLE triples_o (
|
||||
collection text,
|
||||
o text,
|
||||
s text,
|
||||
p text,
|
||||
PRIMARY KEY ((collection, o), s, p)
|
||||
);
|
||||
```
|
||||
**Оптимизирует:** get_o
|
||||
**Ключ разделения:** (collection, o) - Прямой доступ по объекту
|
||||
**Кластеризация:** (s, p) - Эффективный обход по субъекту-предикату
|
||||
|
||||
**Таблица 4: Управление коллекциями и запросы SPO (triples_collection)**
|
||||
```sql
|
||||
CREATE TABLE triples_collection (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
**Оптимизирует:** get_spo, delete_collection
|
||||
**Разделительный ключ:** только коллекция - Обеспечивает эффективные операции на уровне коллекций.
|
||||
**Кластеризация:** (s, p, o) - Стандартный порядок троек.
|
||||
**Назначение:** Двойное использование для точного поиска SPO и в качестве индекса удаления.
|
||||
|
||||
### Отображение запросов
|
||||
|
||||
| Исходный запрос | Целевая таблица | Улучшение производительности |
|
||||
|----------------|-------------|------------------------|
|
||||
| get_all(collection) | triples_s | ALLOW FILTERING (приемлемо для сканирования) |
|
||||
| get_s(collection, s) | triples_s | Прямой доступ к разделу |
|
||||
| get_p(collection, p) | triples_p | Прямой доступ к разделу |
|
||||
| get_o(collection, o) | triples_o | Прямой доступ к разделу |
|
||||
| get_sp(collection, s, p) | triples_s | Раздел + кластеризация |
|
||||
| get_po(collection, p, o) | triples_p | **Больше не требуется ALLOW FILTERING!** |
|
||||
| get_os(collection, o, s) | triples_o | Раздел + кластеризация |
|
||||
| get_spo(collection, s, p, o) | triples_collection | Точный поиск по ключу |
|
||||
| delete_collection(collection) | triples_collection | Чтение индекса, пакетное удаление всех |
|
||||
|
||||
### Стратегия удаления коллекций
|
||||
|
||||
С составными раздельными ключами мы не можем просто выполнить `DELETE FROM table WHERE collection = ?`. Вместо этого:
|
||||
|
||||
1. **Фаза чтения:** Запрос `triples_collection` для перечисления всех троек:
|
||||
```sql
|
||||
SELECT s, p, o FROM triples_collection WHERE collection = ?
|
||||
```
|
||||
Это эффективно, поскольку `collection` является ключом секции для этой таблицы.
|
||||
|
||||
2. **Фаза удаления:** Для каждой тройки (s, p, o) удалите из всех 4 таблиц, используя полные ключи секций:
|
||||
```sql
|
||||
DELETE FROM triples_s WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
DELETE FROM triples_p WHERE collection = ? AND p = ? AND o = ? AND s = ?
|
||||
DELETE FROM triples_o WHERE collection = ? AND o = ? AND s = ? AND p = ?
|
||||
DELETE FROM triples_collection WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
```
|
||||
Обрабатывается пакетами по 100 элементов для повышения эффективности.
|
||||
|
||||
**Анализ компромиссов:**
|
||||
✅ Поддерживает оптимальную производительность запросов с использованием распределенных разделов.
|
||||
✅ Отсутствуют "горячие" разделы для больших коллекций.
|
||||
❌ Более сложная логика удаления (чтение, а затем удаление).
|
||||
❌ Время удаления пропорционально размеру коллекции.
|
||||
|
||||
### Преимущества
|
||||
|
||||
1. **Устраняет ALLOW FILTERING** - Каждый запрос имеет оптимальный путь доступа (за исключением полного сканирования).
|
||||
2. **Не требуются вторичные индексы** - Каждая таблица ЯВЛЯЕТСЯ индексом для своего шаблона запросов.
|
||||
3. **Более равномерное распределение данных** - Композитные ключи разделов эффективно распределяют нагрузку.
|
||||
4. **Предсказуемая производительность** - Время выполнения запроса пропорционально размеру результата, а не общему объему данных.
|
||||
5. **Использует сильные стороны Cassandra** - Разработана с учетом архитектуры Cassandra.
|
||||
6. **Позволяет удалять коллекции** - `triples_collection` служит индексом для удаления.
|
||||
|
||||
## План реализации
|
||||
|
||||
### Файлы, требующие изменений
|
||||
|
||||
#### Основной файл реализации
|
||||
|
||||
**`trustgraph-flow/trustgraph/direct/cassandra_kg.py`** - Требуется полная переработка.
|
||||
|
||||
**Методы, требующие рефакторинга:**
|
||||
```python
|
||||
# Schema initialization
|
||||
def init(self) -> None # Replace single table with three tables
|
||||
|
||||
# Insert operations
|
||||
def insert(self, collection, s, p, o) -> None # Write to all three tables
|
||||
|
||||
# Query operations (API unchanged, implementation optimized)
|
||||
def get_all(self, collection, limit=50) # Use triples_by_subject
|
||||
def get_s(self, collection, s, limit=10) # Use triples_by_subject
|
||||
def get_p(self, collection, p, limit=10) # Use triples_by_po
|
||||
def get_o(self, collection, o, limit=10) # Use triples_by_object
|
||||
def get_sp(self, collection, s, p, limit=10) # Use triples_by_subject
|
||||
def get_po(self, collection, p, o, limit=10) # Use triples_by_po (NO ALLOW FILTERING!)
|
||||
def get_os(self, collection, o, s, limit=10) # Use triples_by_subject
|
||||
def get_spo(self, collection, s, p, o, limit=10) # Use triples_by_subject
|
||||
|
||||
# Collection management
|
||||
def delete_collection(self, collection) -> None # Delete from all three tables
|
||||
```
|
||||
|
||||
#### Интеграционные файлы (изменения в логике не требуются)
|
||||
|
||||
**`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`**
|
||||
Изменения не требуются - используется существующий API KnowledgeGraph.
|
||||
Автоматически получает преимущества от улучшений производительности.
|
||||
|
||||
**`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`**
|
||||
Изменения не требуются - используется существующий API KnowledgeGraph.
|
||||
Автоматически получает преимущества от улучшений производительности.
|
||||
|
||||
### Файлы для тестирования, требующие обновления
|
||||
|
||||
#### Юнит-тесты
|
||||
**`tests/unit/test_storage/test_triples_cassandra_storage.py`**
|
||||
Обновить ожидаемые результаты тестов в связи с изменениями схемы.
|
||||
Добавить тесты для обеспечения согласованности между несколькими таблицами.
|
||||
Проверить отсутствие использования ALLOW FILTERING в планах запросов.
|
||||
|
||||
**`tests/unit/test_query/test_triples_cassandra_query.py`**
|
||||
Обновить утверждения о производительности.
|
||||
Протестировать все 8 шаблонов запросов для новых таблиц.
|
||||
Проверить маршрутизацию запросов к правильным таблицам.
|
||||
|
||||
#### Интеграционные тесты
|
||||
**`tests/integration/test_cassandra_integration.py`**
|
||||
Комплексное тестирование с новой схемой.
|
||||
Сравнение результатов бенчмаркинга производительности.
|
||||
Проверка согласованности данных между таблицами.
|
||||
|
||||
**`tests/unit/test_storage/test_cassandra_config_integration.py`**
|
||||
Обновить тесты проверки схемы.
|
||||
Протестировать сценарии миграции.
|
||||
|
||||
### Стратегия реализации
|
||||
|
||||
#### Фаза 1: Схема и основные методы
|
||||
1. **Переписать метод `init()`** - Создать четыре таблицы вместо одной.
|
||||
2. **Переписать метод `insert()`** - Выполнять пакетные записи во все четыре таблицы.
|
||||
3. **Реализовать подготовленные запросы** - Для оптимальной производительности.
|
||||
4. **Добавить логику маршрутизации таблиц** - Направлять запросы к оптимальным таблицам.
|
||||
5. **Реализовать удаление коллекций** - Читать из triples_collection, пакетно удалять из всех таблиц.
|
||||
|
||||
#### Фаза 2: Оптимизация методов запросов
|
||||
1. **Переписать каждый метод get_*** для использования оптимальной таблицы.
|
||||
2. **Удалить все случаи использования ALLOW FILTERING**.
|
||||
3. **Реализовать эффективное использование ключей кластеризации**.
|
||||
4. **Добавить логирование производительности запросов**.
|
||||
|
||||
#### Фаза 3: Управление коллекциями
|
||||
1. **Обновить `delete_collection()`** - Удалить из всех трех таблиц.
|
||||
2. **Добавить проверку согласованности** - Обеспечить синхронизацию всех таблиц.
|
||||
3. **Реализовать пакетные операции** - Для атомарных операций с несколькими таблицами.
|
||||
|
||||
### Ключевые детали реализации
|
||||
|
||||
#### Стратегия пакетной записи
|
||||
```python
|
||||
def insert(self, collection, s, p, o):
|
||||
batch = BatchStatement()
|
||||
|
||||
# Insert into all four tables
|
||||
batch.add(self.insert_subject_stmt, (collection, s, p, o))
|
||||
batch.add(self.insert_po_stmt, (collection, p, o, s))
|
||||
batch.add(self.insert_object_stmt, (collection, o, s, p))
|
||||
batch.add(self.insert_collection_stmt, (collection, s, p, o))
|
||||
|
||||
self.session.execute(batch)
|
||||
```
|
||||
|
||||
#### Логика маршрутизации запросов
|
||||
```python
|
||||
def get_po(self, collection, p, o, limit=10):
|
||||
# Route to triples_p table - NO ALLOW FILTERING!
|
||||
return self.session.execute(
|
||||
self.get_po_stmt,
|
||||
(collection, p, o, limit)
|
||||
)
|
||||
|
||||
def get_spo(self, collection, s, p, o, limit=10):
|
||||
# Route to triples_collection table for exact SPO lookup
|
||||
return self.session.execute(
|
||||
self.get_spo_stmt,
|
||||
(collection, s, p, o, limit)
|
||||
)
|
||||
```
|
||||
|
||||
#### Логика удаления коллекции
|
||||
```python
|
||||
def delete_collection(self, collection):
|
||||
# Step 1: Read all triples from collection table
|
||||
rows = self.session.execute(
|
||||
f"SELECT s, p, o FROM {self.collection_table} WHERE collection = %s",
|
||||
(collection,)
|
||||
)
|
||||
|
||||
# Step 2: Batch delete from all 4 tables
|
||||
batch = BatchStatement()
|
||||
count = 0
|
||||
|
||||
for row in rows:
|
||||
s, p, o = row.s, row.p, row.o
|
||||
|
||||
# Delete using full partition keys for each table
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.subject_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.po_table} WHERE collection = ? AND p = ? AND o = ? AND s = ?"
|
||||
), (collection, p, o, s))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.object_table} WHERE collection = ? AND o = ? AND s = ? AND p = ?"
|
||||
), (collection, o, s, p))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.collection_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
count += 1
|
||||
|
||||
# Execute every 100 triples to avoid oversized batches
|
||||
if count % 100 == 0:
|
||||
self.session.execute(batch)
|
||||
batch = BatchStatement()
|
||||
|
||||
# Execute remaining deletions
|
||||
if count % 100 != 0:
|
||||
self.session.execute(batch)
|
||||
|
||||
logger.info(f"Deleted {count} triples from collection {collection}")
|
||||
```
|
||||
|
||||
#### Оптимизация подготовленных выражений
|
||||
```python
|
||||
def prepare_statements(self):
|
||||
# Cache prepared statements for better performance
|
||||
self.insert_subject_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.subject_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_po_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.po_table} (collection, p, o, s) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_object_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.object_table} (collection, o, s, p) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_collection_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.collection_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
# ... query statements
|
||||
```
|
||||
|
||||
## Стратегия миграции
|
||||
|
||||
### Подход к миграции данных
|
||||
|
||||
#### Вариант 1: Развертывание Blue-Green (Рекомендуется)
|
||||
1. **Разверните новую схему параллельно с существующей** - Временно используйте разные имена таблиц.
|
||||
2. **Период двойной записи** - Записывайте данные как в старую, так и в новую схемы во время перехода.
|
||||
3. **Фоновая миграция** - Скопируйте существующие данные в новые таблицы.
|
||||
4. **Перенаправление операций чтения** - Направляйте запросы к новым таблицам после миграции данных.
|
||||
5. **Удаление старых таблиц** - После периода проверки.
|
||||
|
||||
#### Вариант 2: Миграция на месте
|
||||
1. **Добавление схемы** - Создайте новые таблицы в существующем пространстве ключей.
|
||||
2. **Скрипт миграции данных** - Пакетная копия из старой таблицы в новые таблицы.
|
||||
3. **Обновление приложения** - Разверните новый код после завершения миграции.
|
||||
4. **Очистка старой таблицы** - Удалите старую таблицу и индексы.
|
||||
|
||||
### Обратная совместимость
|
||||
|
||||
#### Стратегия развертывания
|
||||
```python
|
||||
# Environment variable to control table usage during migration
|
||||
USE_LEGACY_TABLES = os.getenv('CASSANDRA_USE_LEGACY', 'false').lower() == 'true'
|
||||
|
||||
class KnowledgeGraph:
|
||||
def __init__(self, ...):
|
||||
if USE_LEGACY_TABLES:
|
||||
self.init_legacy_schema()
|
||||
else:
|
||||
self.init_optimized_schema()
|
||||
```
|
||||
|
||||
#### Скрипт миграции
|
||||
```python
|
||||
def migrate_data():
|
||||
# Read from old table
|
||||
old_triples = session.execute("SELECT collection, s, p, o FROM triples")
|
||||
|
||||
# Batch write to new tables
|
||||
for batch in batched(old_triples, 100):
|
||||
batch_stmt = BatchStatement()
|
||||
for row in batch:
|
||||
# Add to all three new tables
|
||||
batch_stmt.add(insert_subject_stmt, row)
|
||||
batch_stmt.add(insert_po_stmt, (row.collection, row.p, row.o, row.s))
|
||||
batch_stmt.add(insert_object_stmt, (row.collection, row.o, row.s, row.p))
|
||||
session.execute(batch_stmt)
|
||||
```
|
||||
|
||||
### Стратегия проверки
|
||||
|
||||
#### Проверки согласованности данных
|
||||
```python
|
||||
def validate_migration():
|
||||
# Count total records in old vs new tables
|
||||
old_count = session.execute("SELECT COUNT(*) FROM triples WHERE collection = ?", (collection,))
|
||||
new_count = session.execute("SELECT COUNT(*) FROM triples_by_subject WHERE collection = ?", (collection,))
|
||||
|
||||
assert old_count == new_count, f"Record count mismatch: {old_count} vs {new_count}"
|
||||
|
||||
# Spot check random samples
|
||||
sample_queries = generate_test_queries()
|
||||
for query in sample_queries:
|
||||
old_result = execute_legacy_query(query)
|
||||
new_result = execute_optimized_query(query)
|
||||
assert old_result == new_result, f"Query results differ for {query}"
|
||||
```
|
||||
|
||||
## Стратегия тестирования
|
||||
|
||||
### Тестирование производительности
|
||||
|
||||
#### Сценарии для бенчмаркинга
|
||||
1. **Сравнение производительности запросов**
|
||||
Показатели производительности до и после для всех 8 типов запросов
|
||||
Акцент на улучшении производительности запроса `get_po` (удаление `ALLOW FILTERING`)
|
||||
Измерение задержки запросов при различных объемах данных
|
||||
|
||||
2. **Тестирование нагрузки**
|
||||
Одновременное выполнение запросов
|
||||
Скорость записи с использованием пакетных операций
|
||||
Использование памяти и ЦП
|
||||
|
||||
3. **Тестирование масштабируемости**
|
||||
Производительность при увеличении размеров коллекций
|
||||
Распределение запросов по нескольким коллекциям
|
||||
Использование узлов кластера
|
||||
|
||||
#### Наборы тестовых данных
|
||||
**Маленький:** 10 тысяч троек на коллекцию
|
||||
**Средний:** 100 тысяч троек на коллекцию
|
||||
**Большой:** 1 миллион и более троек на коллекцию
|
||||
**Несколько коллекций:** Тестирование распределения партиций
|
||||
|
||||
### Функциональное тестирование
|
||||
|
||||
#### Обновления модульных тестов
|
||||
```python
|
||||
# Example test structure for new implementation
|
||||
class TestCassandraKGPerformance:
|
||||
def test_get_po_no_allow_filtering(self):
|
||||
# Verify get_po queries don't use ALLOW FILTERING
|
||||
with patch('cassandra.cluster.Session.execute') as mock_execute:
|
||||
kg.get_po('test_collection', 'predicate', 'object')
|
||||
executed_query = mock_execute.call_args[0][0]
|
||||
assert 'ALLOW FILTERING' not in executed_query
|
||||
|
||||
def test_multi_table_consistency(self):
|
||||
# Verify all tables stay in sync
|
||||
kg.insert('test', 's1', 'p1', 'o1')
|
||||
|
||||
# Check all tables contain the triple
|
||||
assert_triple_exists('triples_by_subject', 'test', 's1', 'p1', 'o1')
|
||||
assert_triple_exists('triples_by_po', 'test', 'p1', 'o1', 's1')
|
||||
assert_triple_exists('triples_by_object', 'test', 'o1', 's1', 'p1')
|
||||
```
|
||||
|
||||
#### Обновления результатов интеграционного тестирования
|
||||
```python
|
||||
class TestCassandraIntegration:
|
||||
def test_query_performance_regression(self):
|
||||
# Ensure new implementation is faster than old
|
||||
old_time = benchmark_legacy_get_po()
|
||||
new_time = benchmark_optimized_get_po()
|
||||
assert new_time < old_time * 0.5 # At least 50% improvement
|
||||
|
||||
def test_end_to_end_workflow(self):
|
||||
# Test complete write -> query -> delete cycle
|
||||
# Verify no performance degradation in integration
|
||||
```
|
||||
|
||||
### План отката
|
||||
|
||||
#### Быстрая стратегия отката
|
||||
1. **Переключение переменной окружения** - Немедленный возврат к устаревшим таблицам.
|
||||
2. **Сохранение устаревших таблиц** - Не удалять до тех пор, пока производительность не будет подтверждена.
|
||||
3. **Сигналы мониторинга** - Автоматический запуск отката на основе показателей ошибок/задержек.
|
||||
|
||||
#### Проверка отката
|
||||
```python
|
||||
def rollback_to_legacy():
|
||||
# Set environment variable
|
||||
os.environ['CASSANDRA_USE_LEGACY'] = 'true'
|
||||
|
||||
# Restart services to pick up change
|
||||
restart_cassandra_services()
|
||||
|
||||
# Validate functionality
|
||||
run_smoke_tests()
|
||||
```
|
||||
|
||||
## Риски и соображения
|
||||
|
||||
### Риски производительности
|
||||
**Увеличение времени записи** - 4 операции записи на каждую вставку (на 33% больше, чем при использовании 3-х таблиц)
|
||||
**Избыточность хранения** - В 4 раза больше места для хранения (на 33% больше, чем при использовании 3-х таблиц)
|
||||
**Сбои пакетной записи** - Требуется правильная обработка ошибок
|
||||
**Сложность удаления** - Удаление коллекции требует цикла "чтение-удаление"
|
||||
|
||||
### Операционные риски
|
||||
**Сложность миграции** - Миграция данных для больших наборов данных
|
||||
**Проблемы с согласованностью** - Обеспечение синхронизации всех таблиц
|
||||
**Недостаточность мониторинга** - Необходимы новые метрики для операций с несколькими таблицами
|
||||
|
||||
### Стратегии смягчения
|
||||
1. **Постепенное внедрение** - Начните с небольших коллекций
|
||||
2. **Комплексный мониторинг** - Отслеживайте все метрики производительности
|
||||
3. **Автоматизированная проверка** - Постоянная проверка согласованности
|
||||
4. **Возможность быстрого отката** - Выбор таблицы на основе среды
|
||||
|
||||
## Критерии успеха
|
||||
|
||||
### Улучшения производительности
|
||||
[ ] **Устранение ALLOW FILTERING** - Запросы get_po и get_os выполняются без фильтрации
|
||||
[ ] **Сокращение задержки запросов** - Улучшение времени отклика запросов на 50% или более
|
||||
[ ] **Более равномерное распределение нагрузки** - Отсутствие "горячих" партиций, равномерная нагрузка на узлы кластера
|
||||
[ ] **Масштабируемая производительность** - Время запроса пропорционально размеру результата, а не общему объему данных
|
||||
|
||||
### Функциональные требования
|
||||
[ ] **Совместимость API** - Весь существующий код продолжает работать без изменений
|
||||
[ ] **Согласованность данных** - Все три таблицы остаются синхронизированными
|
||||
[ ] **Отсутствие потери данных** - Миграция сохраняет все существующие тройки
|
||||
[ ] **Обратная совместимость** - Возможность отката к устаревшей схеме
|
||||
|
||||
### Операционные требования
|
||||
[ ] **Безопасная миграция** - Развертывание по принципу "синий-зеленый" с возможностью отката
|
||||
[ ] **Покрытие мониторингом** - Комплексные метрики для операций с несколькими таблицами
|
||||
[ ] **Покрытие тестами** - Все шаблоны запросов протестированы с использованием эталонных показателей производительности
|
||||
[ ] **Документация** - Обновленные процедуры развертывания и эксплуатации
|
||||
|
||||
## План
|
||||
|
||||
### Фаза 1: Реализация
|
||||
[ ] Переписать `cassandra_kg.py` с использованием схемы нескольких таблиц
|
||||
[ ] Реализовать пакетные операции записи
|
||||
[ ] Добавить оптимизацию с использованием подготовленных выражений
|
||||
[ ] Обновить модульные тесты
|
||||
|
||||
### Фаза 2: Интеграционное тестирование
|
||||
[ ] Обновить интеграционные тесты
|
||||
[ ] Эталонное тестирование производительности
|
||||
[ ] Тестирование нагрузки с использованием реалистичных объемов данных
|
||||
[ ] Скрипты проверки согласованности данных
|
||||
|
||||
### Фаза 3: Планирование миграции
|
||||
[ ] Скрипты развертывания по принципу "синий-зеленый"
|
||||
[ ] Инструменты миграции данных
|
||||
[ ] Обновления панели мониторинга
|
||||
[ ] Процедуры отката
|
||||
|
||||
### Фаза 4: Развертывание в производственной среде
|
||||
[ ] Поэтапное развертывание в производственной среде
|
||||
[ ] Мониторинг и проверка производительности
|
||||
[ ] Очистка устаревших таблиц
|
||||
[ ] Обновление документации
|
||||
|
||||
## Заключение
|
||||
|
||||
Эта стратегия денормализации с использованием нескольких таблиц напрямую решает две критические проблемы производительности:
|
||||
|
||||
1. **Устраняет дорогостоящий ALLOW FILTERING**, предоставляя оптимальные структуры таблиц для каждого шаблона запроса
|
||||
2. **Улучшает эффективность кластеризации** за счет составных ключей партиций, которые правильно распределяют нагрузку
|
||||
|
||||
Этот подход использует сильные стороны Cassandra, сохраняя при этом полную совместимость API, что обеспечивает автоматическое получение преимуществ от улучшений производительности для существующего кода.
|
||||
687
docs/tech-specs/cassandra-performance-refactor.sw.md
Normal file
687
docs/tech-specs/cassandra-performance-refactor.sw.md
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Maelezo ya Kiufundi: Uboreshaji wa Utendaji wa Hifadhidata ya Maarifa ya Cassandra"
|
||||
parent: "Swahili (Beta)"
|
||||
---
|
||||
|
||||
# Maelezo ya Kiufundi: Uboreshaji wa Utendaji wa Hifadhidata ya Maarifa ya Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**Hali:** Rasimu
|
||||
**Mwandishi:** Msaidizi
|
||||
**Tarehe:** 2025-09-18
|
||||
|
||||
## Muhtasari
|
||||
|
||||
Maelezo haya yanashughulikia masuala ya utendaji katika utekelezaji wa hifadhidata ya maarifa ya TrustGraph ya Cassandra na yanapendekeza uboreshaji kwa uhifadhi na utafutaji wa data ya RDF.
|
||||
|
||||
## Utendaji wa Sasa
|
||||
|
||||
### Muundo wa Skimu
|
||||
|
||||
Utendaji wa sasa hutumia muundo wa jedwali moja katika `trustgraph-flow/trustgraph/direct/cassandra_kg.py`:
|
||||
|
||||
```sql
|
||||
CREATE TABLE triples (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
|
||||
**Faharasa Pili:**
|
||||
`triples_s` KWA `s` (somo)
|
||||
`triples_p` KWA `p` (kitenzi)
|
||||
`triples_o` KWA `o` (kielele)
|
||||
|
||||
### Mifumo ya Umasiliano
|
||||
|
||||
Utaratibu wa sasa unaoendeshwa unao na mifumo 8 tofauti ya masiliano:
|
||||
|
||||
1. **get_all(mkusanyiko, kikomo=50)** - Pata vitriple vyote kwa mkusanyiko
|
||||
```sql
|
||||
SELECT s, p, o FROM triples WHERE collection = ? LIMIT 50
|
||||
```
|
||||
|
||||
2. **get_s(collection, s, limit=10)** - Utafiti kwa mada.
|
||||
```sql
|
||||
SELECT p, o FROM triples WHERE collection = ? AND s = ? LIMIT 10
|
||||
```
|
||||
|
||||
3. **get_p(collection, p, limit=10)** - Utafiti kwa kutumia vigezo.
|
||||
```sql
|
||||
SELECT s, o FROM triples WHERE collection = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
4. **get_o(collection, o, limit=10)** - Utafiti kwa kutumia kitu.
|
||||
```sql
|
||||
SELECT s, p FROM triples WHERE collection = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
5. **get_sp(collection, s, p, limit=10)** - Utafiti kwa mada + predikati
|
||||
```sql
|
||||
SELECT o FROM triples WHERE collection = ? AND s = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
6. **get_po(collection, p, o, limit=10)** - Utafiti kwa kutumia vigezo na kitu ⚠️
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
7. **get_os(collection, o, s, limit=10)** - Utafiti kwa kutumia kitu pamoja na mada ⚠️
|
||||
```sql
|
||||
SELECT p FROM triples WHERE collection = ? AND o = ? AND s = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
8. **get_spo(collection, s, p, o, limit=10)** - Mechi kamili ya triple.
|
||||
```sql
|
||||
SELECT s as x FROM triples WHERE collection = ? AND s = ? AND p = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
### Muundo wa Sasa
|
||||
|
||||
**Faili: `trustgraph-flow/trustgraph/direct/cassandra_kg.py`**
|
||||
Darasa moja la `KnowledgeGraph` linaloshughulikia shughuli zote
|
||||
Uunganisho wa kikundi kupitia orodha ya kimataifa ya `_active_clusters`
|
||||
Jina la jedwali lililobainishwa: `"triples"`
|
||||
Spishi kwa kila mfumo wa mtumiaji
|
||||
Nakala ya SimpleStrategy kwa sababu 1
|
||||
|
||||
**Maeneo ya Uunganisho:**
|
||||
**Njia ya Kuandika:** `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
**Njia ya Umasilisho:** `trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
**Hifadhi ya Maarifa:** `trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
|
||||
## Matatizo ya Utendaji Yanayobainika
|
||||
|
||||
### Matatizo ya Ngazi ya Muundo
|
||||
|
||||
1. **Muundo Usiofaa wa Ufunguo Mkuu**
|
||||
Sasa: `PRIMARY KEY (collection, s, p, o)`
|
||||
Hupelekea uwekaji duni wa data kwa mifumo ya kawaida ya ufikiaji
|
||||
Inahitaji matumizi ya gharama kubwa ya fahirisi za sekondari
|
||||
|
||||
2. **Matumizi Mengi ya Fahirisi za Sekondari** ⚠️
|
||||
Fahirisi tatu za sekondari kwenye safu zenye maadili mengi (s, p, o)
|
||||
Fahirisi za sekondari katika Cassandra ni ghali na hazipunguzi kasi vizuri
|
||||
Maswali 6 na 7 yanahitaji `ALLOW FILTERING`, ambayo inaonyesha muundo duni wa data
|
||||
|
||||
3. **Hatari ya Sehemu Zenye Trafiki Kubwa**
|
||||
Ufunguo mmoja wa sehemu `collection` unaweza kuunda sehemu zenye trafiki kubwa
|
||||
Mkusanyiko mkubwa utajikuta katika nodi moja
|
||||
Hakuna mkakati wa usambazaji wa mizigo
|
||||
|
||||
### Matatizo ya Ngazi ya Umasilisho
|
||||
|
||||
1. **Matumizi ya ALLOW FILTERING** ⚠️
|
||||
Aina mbili za maswali (get_po, get_os) zinahitaji `ALLOW FILTERING`
|
||||
Maswali haya husifia sehemu nyingi na ni ghali sana
|
||||
Utendaji unapungua kwa kasi kadri ya ukubwa wa data
|
||||
|
||||
2. **Mifumo ya Ufikiaji Yasiyo na Ufanisi**
|
||||
Hakuna uboreshaji kwa mifumo ya kawaida ya maswali ya RDF
|
||||
Hakuna fahirisi za pamoja kwa mchanganyiko wa maswali unaoonekana mara kwa mara
|
||||
Hakuna utambuzi wa mifumo ya utaftaji wa grafu
|
||||
|
||||
3. **Ukosefu wa Uboreshaji wa Umasilisho**
|
||||
Hakuna kuhifadhi kwa masimulizi yaliyotayarishwa
|
||||
Hakuna vidokezo au mikakati ya uboreshaji wa maswali
|
||||
Hakuna utambuzi wa upangishaji zaidi ya LIMIT rahisi
|
||||
|
||||
## Taarifa ya Tatizo
|
||||
|
||||
Utekelezaji wa sasa wa hifadhi ya maarifa ya Cassandra una matatizo mawili muhimu ya utendaji:
|
||||
|
||||
### 1. Utendaji Usio na Ufanisi wa Maswali ya get_po
|
||||
|
||||
Swali la `get_po(collection, p, o)` halipunguzi kasi kwa sababu linahitaji `ALLOW FILTERING`:
|
||||
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
**Sababu ya kuwa hii ni tatizo:**
|
||||
`ALLOW FILTERING` inalazimisha Cassandra kuchanganua kila sehemu ndani ya mkusanyiko.
|
||||
Utendaji hupungua kwa mstari sawa na ukubwa wa data.
|
||||
Hii ni muundo wa kawaida wa swali la RDF (kutafuta vitu ambavyo vina uhusiano maalum wa tabia-jambo).
|
||||
Huunda mzigo mkubwa kwenye kundi kadri data inavyoongezeka.
|
||||
|
||||
### 2. Mkakati Usiofaa wa Uwekaji Pamoja
|
||||
|
||||
Ufunguo mkuu wa sasa `PRIMARY KEY (collection, s, p, o)` hutoa faida ndogo katika uwekaji pamoja:
|
||||
|
||||
**Matatizo na uwekaji pamoja wa sasa:**
|
||||
`collection` kama funguo ya sehemu haisambati data kwa ufanisi.
|
||||
Makusanyiko mengi yana data tofauti, na kuifanya uwekaji pamoja kuwa usiofaa.
|
||||
Hakuna utambuzi kwa mifumo ya kawaida ya ufikiaji katika maswali ya RDF.
|
||||
Makusanyiko makubwa huunda sehemu zenye mzigo mwingi kwenye nodi moja.
|
||||
Safu za uwekaji pamoja (s, p, o) haziboreshi kwa mifumo ya kawaida ya utaftaji wa grafu.
|
||||
|
||||
**Athari:**
|
||||
Maswali hayanapata faida kutoka kwa ukaribu wa data.
|
||||
Matumizi duni ya kumbukumbu (cache).
|
||||
Usambazaji usio sawa wa mzigo katika nodi za kundi.
|
||||
Zuio la uwezo wa kupanuka (scalability) kadri makusanyiko yanavyoongezeka.
|
||||
|
||||
## Suluhisho Lililopendekezwa: Mkakati wa Utofauti wa Jedwali 4
|
||||
|
||||
### Muhtasari
|
||||
|
||||
Badilisha jedwali moja `triples` na jedwali nne zilizoundwa kwa madhumuni maalum, kila moja iliyoboreshwa kwa mifumo maalum ya swali. Hii inafutilia hitaji la fahirisi za sekondari na ALLOW FILTERING huku ikiwapa utendaji bora kwa aina zote za swali. Jedwali la nne linaruhusu uondoaji wa makusanyiko kwa ufanisi licha ya funguo za sehemu zilizounganishwa.
|
||||
|
||||
### Muundo Mpya wa Skimu
|
||||
|
||||
**Jedwali la 1: Maswali Yanayozingatia Sijali (triples_s)**
|
||||
```sql
|
||||
CREATE TABLE triples_s (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY ((collection, s), p, o)
|
||||
);
|
||||
```
|
||||
**Inaboresha:** get_s, get_sp, get_os
|
||||
**Ufunguo wa Sehemu:** (mkusanyiko, s) - Usambazaji bora kuliko mkusanyiko pekee
|
||||
**Kukusanya:** (p, o) - Huwezesha utafutaji wa ufanisi wa vigezo/vitendo kwa ajili ya somo
|
||||
|
||||
**Jedwali 2: Maswali ya Vigezo-Vitendo (triples_p)**
|
||||
```sql
|
||||
CREATE TABLE triples_p (
|
||||
collection text,
|
||||
p text,
|
||||
o text,
|
||||
s text,
|
||||
PRIMARY KEY ((collection, p), o, s)
|
||||
);
|
||||
```
|
||||
**Inaboresha:** get_p, get_po (inabadilisha ALLOW FILTERING!)
|
||||
**Ufunguo wa Sehemu:** (mkusanyiko, p) - Ufikiaji wa moja kwa moja kupitia kigezo.
|
||||
**Kukusanyika:** (o, s) - Ufuatiliaji wa vitu na masomo unaofaa.
|
||||
|
||||
**Jedwali la 3: Maswali Yanayozingatia Vitu (triples_o)**
|
||||
```sql
|
||||
CREATE TABLE triples_o (
|
||||
collection text,
|
||||
o text,
|
||||
s text,
|
||||
p text,
|
||||
PRIMARY KEY ((collection, o), s, p)
|
||||
);
|
||||
```
|
||||
**Inaboresha:** get_o
|
||||
**Ufunguo wa Sehemu:** (mkusanyiko, o) - Ufikiaji wa moja kwa moja kwa kutumia kitu
|
||||
**Kukusanya:** (s, p) - Ufuatiliaji wa ufanisi wa somo-tabia
|
||||
|
||||
**Jedwali la 4: Usimamizi wa Mkusaniko na Maswali ya SPO (triples_collection)**
|
||||
```sql
|
||||
CREATE TABLE triples_collection (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
**Inaboresha:** get_spo, delete_collection
|
||||
**Ufunguo wa Sehemu (Partition Key):** mkusanyiko pekee - Huwezesha operesheni bora za kiwango cha mkusanyiko.
|
||||
**Kukusanyika (Clustering):** (s, p, o) - Mpangilio wa kawaida wa triple.
|
||||
**Madhumuni:** Matumizi mawili, kwa utafutaji sahihi wa SPO na kama faharasa ya kufuta.
|
||||
|
||||
### Ramani ya Utafutaji (Query Mapping)
|
||||
|
||||
| Utafutaji Asili | Jedwali Linalolengwa | Ubora wa Kuboresha |
|
||||
|----------------|-------------|------------------------|
|
||||
| get_all(collection) | triples_s | RUHASA YA KUCHANUA (inayokubalika kwa skani) |
|
||||
| get_s(collection, s) | triples_s | Ufikiaji wa moja kwa moja wa sehemu. |
|
||||
| get_p(collection, p) | triples_p | Ufikiaji wa moja kwa moja wa sehemu. |
|
||||
| get_o(collection, o) | triples_o | Ufikiaji wa moja kwa moja wa sehemu. |
|
||||
| get_sp(collection, s, p) | triples_s | Sehemu + kukusanyika. |
|
||||
| get_po(collection, p, o) | triples_p | **HAKUNA tena RUHASA LA KUCHANUA!** |
|
||||
| get_os(collection, o, s) | triples_o | Sehemu + kukusanyika. |
|
||||
| get_spo(collection, s, p, o) | triples_collection | Utafutaji wa ufunguo wa moja kwa moja. |
|
||||
| delete_collection(collection) | triples_collection | Soma faharasa, futa kwa wingi. |
|
||||
|
||||
### Mkakati wa Kufuta Mkusaniko
|
||||
|
||||
Pamoja na ufunguo wa sehemu mchanganyiko, hatuwezi tu kutekeleza `DELETE FROM table WHERE collection = ?`. Badala yake:
|
||||
|
||||
1. **Awamu ya Kusoma:** Tafuta `triples_collection` ili kuorodhesha triple zote:
|
||||
```sql
|
||||
SELECT s, p, o FROM triples_collection WHERE collection = ?
|
||||
```
|
||||
Hii ni bora kwa sababu `collection` ndiyo ufunguo wa kundi kwa jedwali hili.
|
||||
|
||||
2. **Awamu ya Ufutilishaji:** Kwa kila seti tatu (s, p, o), futa kutoka kwenye meza zote 4 kwa kutumia ufunguo kamili wa kundi:
|
||||
```sql
|
||||
DELETE FROM triples_s WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
DELETE FROM triples_p WHERE collection = ? AND p = ? AND o = ? AND s = ?
|
||||
DELETE FROM triples_o WHERE collection = ? AND o = ? AND s = ? AND p = ?
|
||||
DELETE FROM triples_collection WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
```
|
||||
Imefunganishwa katika makundi ya 100 ili kuongeza ufanisi.
|
||||
|
||||
**Uchambuzi wa Usawa:**
|
||||
✅ Inaendelea kudumisha utendaji bora wa maswali kwa kutumia vipande vilivyogawanywa.
|
||||
✅ Hakuna vipande ambavyo hupita kasi kwa makusanyo makubwa.
|
||||
❌ Mantiki ya kufuta ni ngumu zaidi (soma kisha futa).
|
||||
❌ Muda wa kufuta unalingana na ukubwa wa mkusanyiko.
|
||||
|
||||
### Faida
|
||||
|
||||
1. **Inaondoa ALLOW FILTERING** - Kila swali lina njia bora ya kufikia (isipokuwa skani ya get_all).
|
||||
2. **Hakuna Faharasa za Pili** - Kila jedwali NI faharasa kwa mtindo wake wa swali.
|
||||
3. **Usambazaji Bora wa Data** - Funguo za pamoja za kugawanya zinapanua mzigo kwa ufanisi.
|
||||
4. **Utendaji Unaoweza Kushawishiwa** - Muda wa swali unalingana na ukubwa wa matokeo, sio data jumla.
|
||||
5. **Inatumia Nguvu za Cassandra** - Imeundwa kwa usanifu wa Cassandra.
|
||||
6. **Inaruhusu Ufuta wa Makusanyo** - triples_collection hutumika kama faharasa ya kufuta.
|
||||
|
||||
## Mpango wa Utendaji
|
||||
|
||||
### Faili Zinazohitaji Marekebisho
|
||||
|
||||
#### Faili Kuu ya Utendaji
|
||||
|
||||
**`trustgraph-flow/trustgraph/direct/cassandra_kg.py`** - Inahitajika kuandikwa upya kabisa.
|
||||
|
||||
**Mbinu Zinazohitajika Kubadilishwa:**
|
||||
```python
|
||||
# Schema initialization
|
||||
def init(self) -> None # Replace single table with three tables
|
||||
|
||||
# Insert operations
|
||||
def insert(self, collection, s, p, o) -> None # Write to all three tables
|
||||
|
||||
# Query operations (API unchanged, implementation optimized)
|
||||
def get_all(self, collection, limit=50) # Use triples_by_subject
|
||||
def get_s(self, collection, s, limit=10) # Use triples_by_subject
|
||||
def get_p(self, collection, p, limit=10) # Use triples_by_po
|
||||
def get_o(self, collection, o, limit=10) # Use triples_by_object
|
||||
def get_sp(self, collection, s, p, limit=10) # Use triples_by_subject
|
||||
def get_po(self, collection, p, o, limit=10) # Use triples_by_po (NO ALLOW FILTERING!)
|
||||
def get_os(self, collection, o, s, limit=10) # Use triples_by_subject
|
||||
def get_spo(self, collection, s, p, o, limit=10) # Use triples_by_subject
|
||||
|
||||
# Collection management
|
||||
def delete_collection(self, collection) -> None # Delete from all three tables
|
||||
```
|
||||
|
||||
#### Faili za Uunganishaji (Hakuna Mabadiliko ya Mantiki Yanayohitajika)
|
||||
|
||||
**`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`**
|
||||
Hakuna mabadiliko yanayohitajika - hutumia API ya KnowledgeGraph iliyopo
|
||||
Inafaidika moja kwa moja kutoka kwa uboreshaji wa utendaji
|
||||
|
||||
**`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`**
|
||||
Hakuna mabadiliko yanayohitajika - hutumia API ya KnowledgeGraph iliyopo
|
||||
Inafaidika moja kwa moja kutoka kwa uboreshaji wa utendaji
|
||||
|
||||
### Faili za Majaribio Zinazohitaji Mabadiliko
|
||||
|
||||
#### Majaribio ya Kitengo
|
||||
**`tests/unit/test_storage/test_triples_cassandra_storage.py`**
|
||||
Sasisha matarajio ya majaribio kwa mabadiliko ya schema
|
||||
Ongeza majaribio kwa utangamano wa meza nyingi
|
||||
Hakikisha hakuna ALLOW FILTERING katika mipango ya swali
|
||||
|
||||
**`tests/unit/test_query/test_triples_cassandra_query.py`**
|
||||
Sasisha madai ya utendaji
|
||||
Jaribu mifumo yote 8 ya swali dhidi ya meza mpya
|
||||
Hakikisha uelekezaji wa swali hadi meza sahihi
|
||||
|
||||
#### Majaribio ya Uunganishaji
|
||||
**`tests/integration/test_cassandra_integration.py`**
|
||||
Majaribio ya mwisho na schema mpya
|
||||
Ulinganisho wa benchmarking wa utendaji
|
||||
Uthibitisho wa utangamano wa data katika meza
|
||||
|
||||
**`tests/unit/test_storage/test_cassandra_config_integration.py`**
|
||||
Sasisha majaribio ya uthibitisho wa schema
|
||||
Jaribu hali za uhamishaji
|
||||
|
||||
### Mkakati wa Utendaji
|
||||
|
||||
#### Awamu ya 1: Schema na Mbinu za Msingi
|
||||
1. **Andika upya mbinu ya `init()`** - Unda meza nne badala ya moja
|
||||
2. **Andika upya mbinu ya `insert()`** - Andika kwa wingi kwenye meza zote nne
|
||||
3. **Teleza taarifa zilizotayarishwa** - Kwa utendaji bora
|
||||
4. **Ongeza mantiki ya uelekezaji wa meza** - Elekeza maswali hadi meza bora
|
||||
5. **Teleza uondoaji wa mkusanyiko** - Soma kutoka kwa triples_collection, ondoa kwa wingi kutoka kwenye meza zote
|
||||
|
||||
#### Awamu ya 2: Uboreshaji wa Mbinu ya Swali
|
||||
1. **Andika upya kila mbinu ya get_*** ili itumie meza bora
|
||||
2. **Ondoa matumizi yote ya ALLOW FILTERING**
|
||||
3. **Teleza matumizi bora ya ufunguo wa uwekaji**
|
||||
4. **Ongeza uandikaji wa utendaji wa swali**
|
||||
|
||||
#### Awamu ya 3: Usimamizi wa Mkusaniko
|
||||
1. **Sasisha `delete_collection()`** - Ondoa kutoka kwenye meza zote tatu
|
||||
2. **Ongeza uthibitisho wa utangamano** - Hakikisha meza zote zinaendelea kuwa sawa
|
||||
3. **Teleza shughuli za wingi** - Kwa shughuli za meza nyingi za atomiki
|
||||
|
||||
### Maelezo Muhimu ya Utendaji
|
||||
|
||||
#### Mkakati wa Kuandika kwa Wingi
|
||||
```python
|
||||
def insert(self, collection, s, p, o):
|
||||
batch = BatchStatement()
|
||||
|
||||
# Insert into all four tables
|
||||
batch.add(self.insert_subject_stmt, (collection, s, p, o))
|
||||
batch.add(self.insert_po_stmt, (collection, p, o, s))
|
||||
batch.add(self.insert_object_stmt, (collection, o, s, p))
|
||||
batch.add(self.insert_collection_stmt, (collection, s, p, o))
|
||||
|
||||
self.session.execute(batch)
|
||||
```
|
||||
|
||||
#### Mantiki ya Uelekezaji wa Maswali
|
||||
```python
|
||||
def get_po(self, collection, p, o, limit=10):
|
||||
# Route to triples_p table - NO ALLOW FILTERING!
|
||||
return self.session.execute(
|
||||
self.get_po_stmt,
|
||||
(collection, p, o, limit)
|
||||
)
|
||||
|
||||
def get_spo(self, collection, s, p, o, limit=10):
|
||||
# Route to triples_collection table for exact SPO lookup
|
||||
return self.session.execute(
|
||||
self.get_spo_stmt,
|
||||
(collection, s, p, o, limit)
|
||||
)
|
||||
```
|
||||
|
||||
#### Mantiki ya Ufutilishaji wa Mkusanyiko
|
||||
```python
|
||||
def delete_collection(self, collection):
|
||||
# Step 1: Read all triples from collection table
|
||||
rows = self.session.execute(
|
||||
f"SELECT s, p, o FROM {self.collection_table} WHERE collection = %s",
|
||||
(collection,)
|
||||
)
|
||||
|
||||
# Step 2: Batch delete from all 4 tables
|
||||
batch = BatchStatement()
|
||||
count = 0
|
||||
|
||||
for row in rows:
|
||||
s, p, o = row.s, row.p, row.o
|
||||
|
||||
# Delete using full partition keys for each table
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.subject_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.po_table} WHERE collection = ? AND p = ? AND o = ? AND s = ?"
|
||||
), (collection, p, o, s))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.object_table} WHERE collection = ? AND o = ? AND s = ? AND p = ?"
|
||||
), (collection, o, s, p))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.collection_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
count += 1
|
||||
|
||||
# Execute every 100 triples to avoid oversized batches
|
||||
if count % 100 == 0:
|
||||
self.session.execute(batch)
|
||||
batch = BatchStatement()
|
||||
|
||||
# Execute remaining deletions
|
||||
if count % 100 != 0:
|
||||
self.session.execute(batch)
|
||||
|
||||
logger.info(f"Deleted {count} triples from collection {collection}")
|
||||
```
|
||||
|
||||
#### Uboreshaji wa Matamshi Yaliyotayarishwa
|
||||
```python
|
||||
def prepare_statements(self):
|
||||
# Cache prepared statements for better performance
|
||||
self.insert_subject_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.subject_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_po_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.po_table} (collection, p, o, s) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_object_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.object_table} (collection, o, s, p) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_collection_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.collection_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
# ... query statements
|
||||
```
|
||||
|
||||
## Mkakati wa Uhamishaji
|
||||
|
||||
### Mbinu ya Uhamishaji wa Data
|
||||
|
||||
#### Chaguo la 1: Uwekaji wa Blue-Green (Inapendekezwa)
|
||||
1. **Weka mfumo mpya pamoja na mfumo uliopo** - Tumia majina tofauti ya jedwali kwa muda
|
||||
2. **Kipindi cha kuandika mara mbili** - Andika kwenye mifumo ya zamani na mipya wakati wa mabadiliko
|
||||
3. **Uhamishaji wa nyuma** - Nakili data iliyopo kwenye jedwali jipya
|
||||
4. **Badilisha maswali** - Elekeza maswali kwenye jedwali jipya baada ya uhamishaji wa data
|
||||
5. **Futa jedwali la zamani** - Baada ya kipindi cha uhakiki
|
||||
|
||||
#### Chaguo la 2: Uhamishaji wa Moja kwa Moja
|
||||
1. **Kuongeza mfumo** - Unda jedwali jipya kwenye eneo la funguo lililopo
|
||||
2. **Skripti ya uhamishaji wa data** - Nakili kwa wingi kutoka kwenye jedwali la zamani hadi kwenye jedwali jipya
|
||||
3. **Sasisho la programu** - Weka programu mpya baada ya uhamishaji kukamilika
|
||||
4. **Kusafisha jedwali la zamani** - Ondoa jedwali la zamani na fahirisi
|
||||
|
||||
### Utangamano wa Nyuma
|
||||
|
||||
#### Mkakati wa Uwekaji
|
||||
```python
|
||||
# Environment variable to control table usage during migration
|
||||
USE_LEGACY_TABLES = os.getenv('CASSANDRA_USE_LEGACY', 'false').lower() == 'true'
|
||||
|
||||
class KnowledgeGraph:
|
||||
def __init__(self, ...):
|
||||
if USE_LEGACY_TABLES:
|
||||
self.init_legacy_schema()
|
||||
else:
|
||||
self.init_optimized_schema()
|
||||
```
|
||||
|
||||
#### Skripti ya Uhamishaji
|
||||
```python
|
||||
def migrate_data():
|
||||
# Read from old table
|
||||
old_triples = session.execute("SELECT collection, s, p, o FROM triples")
|
||||
|
||||
# Batch write to new tables
|
||||
for batch in batched(old_triples, 100):
|
||||
batch_stmt = BatchStatement()
|
||||
for row in batch:
|
||||
# Add to all three new tables
|
||||
batch_stmt.add(insert_subject_stmt, row)
|
||||
batch_stmt.add(insert_po_stmt, (row.collection, row.p, row.o, row.s))
|
||||
batch_stmt.add(insert_object_stmt, (row.collection, row.o, row.s, row.p))
|
||||
session.execute(batch_stmt)
|
||||
```
|
||||
|
||||
### Mbinu ya Uthibitisho
|
||||
|
||||
#### Vipimo vya Ulinganifu wa Data
|
||||
```python
|
||||
def validate_migration():
|
||||
# Count total records in old vs new tables
|
||||
old_count = session.execute("SELECT COUNT(*) FROM triples WHERE collection = ?", (collection,))
|
||||
new_count = session.execute("SELECT COUNT(*) FROM triples_by_subject WHERE collection = ?", (collection,))
|
||||
|
||||
assert old_count == new_count, f"Record count mismatch: {old_count} vs {new_count}"
|
||||
|
||||
# Spot check random samples
|
||||
sample_queries = generate_test_queries()
|
||||
for query in sample_queries:
|
||||
old_result = execute_legacy_query(query)
|
||||
new_result = execute_optimized_query(query)
|
||||
assert old_result == new_result, f"Query results differ for {query}"
|
||||
```
|
||||
|
||||
## Mbinu ya Majaribio
|
||||
|
||||
### Majaribio ya Utendaji
|
||||
|
||||
#### Hali za Majaribio ya Kiwango
|
||||
1. **Ulinganisho wa Utendaji wa Maswali**
|
||||
Vipimo vya utendaji kabla na baada kwa aina zote 8 za maswali
|
||||
Lenga uboreshaji wa utendaji wa `get_po` (ondoa `ALLOW FILTERING`)
|
||||
Pima muda wa maswali chini ya saizi tofauti za data
|
||||
|
||||
2. **Majaribio ya Upakiaji**
|
||||
Utendaji wa maswali kwa wakati mmoja
|
||||
Uwezo wa kuandika na shughuli za kikundi
|
||||
Matumizi ya kumbukumbu na CPU
|
||||
|
||||
3. **Majaribio ya Uwezo wa Kupanuka**
|
||||
Utendaji na saizi zinazoongezeka za mkusanyiko
|
||||
Usambazaji wa maswali ya mkusanyiko mwingi
|
||||
Matumizi ya nodi za kundi
|
||||
|
||||
#### Kijiko cha Majaribio
|
||||
**Kidogo:** 10K ya vitatu kwa kila mkusanyiko
|
||||
**Katikati:** 100K ya vitatu kwa kila mkusanyiko
|
||||
**Kubwa:** 1M+ ya vitatu kwa kila mkusanyiko
|
||||
**Mkusanyiko mwingi:** Jaribu usambazaji wa sehemu
|
||||
|
||||
### Majaribio ya Utendaji
|
||||
|
||||
#### Marekebisho ya Majaribio ya Kitengo
|
||||
```python
|
||||
# Example test structure for new implementation
|
||||
class TestCassandraKGPerformance:
|
||||
def test_get_po_no_allow_filtering(self):
|
||||
# Verify get_po queries don't use ALLOW FILTERING
|
||||
with patch('cassandra.cluster.Session.execute') as mock_execute:
|
||||
kg.get_po('test_collection', 'predicate', 'object')
|
||||
executed_query = mock_execute.call_args[0][0]
|
||||
assert 'ALLOW FILTERING' not in executed_query
|
||||
|
||||
def test_multi_table_consistency(self):
|
||||
# Verify all tables stay in sync
|
||||
kg.insert('test', 's1', 'p1', 'o1')
|
||||
|
||||
# Check all tables contain the triple
|
||||
assert_triple_exists('triples_by_subject', 'test', 's1', 'p1', 'o1')
|
||||
assert_triple_exists('triples_by_po', 'test', 'p1', 'o1', 's1')
|
||||
assert_triple_exists('triples_by_object', 'test', 'o1', 's1', 'p1')
|
||||
```
|
||||
|
||||
#### Sasisho la Mtihani wa Uunganishaji
|
||||
```python
|
||||
class TestCassandraIntegration:
|
||||
def test_query_performance_regression(self):
|
||||
# Ensure new implementation is faster than old
|
||||
old_time = benchmark_legacy_get_po()
|
||||
new_time = benchmark_optimized_get_po()
|
||||
assert new_time < old_time * 0.5 # At least 50% improvement
|
||||
|
||||
def test_end_to_end_workflow(self):
|
||||
# Test complete write -> query -> delete cycle
|
||||
# Verify no performance degradation in integration
|
||||
```
|
||||
|
||||
### Mpango wa Kurudisha Nyuma
|
||||
|
||||
#### Mbinu ya Kurudisha Nyuma Haraka
|
||||
1. **Kubadili jenereta la mazingira** - Rudi kwenye jedwali la zamani mara moja
|
||||
2. **Endelea kutumia jedwali la zamani** - Usifute hadi utendaji uthibitishwe
|
||||
3. **Arifa za ufuatiliaji** - Vinjari vya kiotomatiki vya kurudisha nyuma kulingana na viwango vya makosa/uwezekano wa kuchelewesha
|
||||
|
||||
#### Uthibitisho wa Kurudisha Nyuma
|
||||
```python
|
||||
def rollback_to_legacy():
|
||||
# Set environment variable
|
||||
os.environ['CASSANDRA_USE_LEGACY'] = 'true'
|
||||
|
||||
# Restart services to pick up change
|
||||
restart_cassandra_services()
|
||||
|
||||
# Validate functionality
|
||||
run_smoke_tests()
|
||||
```
|
||||
|
||||
## Hatari na Mambo ya Kuzingatia
|
||||
|
||||
### Hatari za Utendaji
|
||||
**Kuongezeka kwa muda wa kuandika** - Operesheni 4 za kuandika kwa kila kuingiza (33% zaidi kuliko mfumo wa meza 3)
|
||||
**Uongezekaji wa matumizi ya nafasi** - Mahitaji 4 ya nafasi (33% zaidi kuliko mfumo wa meza 3)
|
||||
**Hitilafu za kuandika kwa wingi** - Inahitajika udhibiti wa makosa unaofaa
|
||||
**Uchaguzi wa kufuta** - Kufuta kwa mkusanyiko inahitaji mzunguko wa kusoma na kisha kufuta
|
||||
|
||||
### Hatari za Uendeshaji
|
||||
**Uchaguzi wa uhamisho** - Uhamishaji wa data kwa data kubwa
|
||||
**Changamoto za utangamano** - Kuhakikisha meza zote zinaendelea kusawazishwa
|
||||
**Mapungufu ya ufuatiliaji** - Inahitajika metriki mpya kwa operesheni za meza nyingi
|
||||
|
||||
### Mikakati ya Kupunguza Hatari
|
||||
1. **Uanzishaji wa hatua kwa hatua** - Anza na mkusanyiko mdogo
|
||||
2. **Ufuatiliaji kamili** - Fuatilia metriki zote za utendaji
|
||||
3. **Uthibitisho otomatiki** - Uchunguzi wa utangamano wa mara kwa mara
|
||||
4. **Uwezo wa kurejesha haraka** - Uchaguzi wa meza kulingana na mazingira
|
||||
|
||||
## Vigezo vya Mafanikio
|
||||
|
||||
### Maboresho ya Utendaji
|
||||
[ ] **Kuondoa ALLOW FILTERING** - Maswali ya `get_po` na `get_os` yanatumika bila kuchujwa
|
||||
[ ] **Kupunguza muda wa swali** - Kuboresha kwa 50% au zaidi katika muda wa majibu ya swali
|
||||
**Usambazaji bora wa mzigo** - Hakuna sehemu zenye mzigo mwingi, usambazaji sare katika kila nodi ya kundi
|
||||
[ ] **Utendaji unaoweza kuongezeka** - Muda wa swali unalingana na ukubwa wa matokeo, sio data jumla
|
||||
|
||||
### Mahitaji ya Utendaji
|
||||
[ ] **Ulinganishaji wa API** - Msimbo wote uliopo unaendelea kufanya kazi bila mabadiliko
|
||||
[ ] **Utangamano wa data** - Meza zote tatu zinaendelea kusawazishwa
|
||||
[ ] **Hakuna upotevu wa data** - Uhamishaji unahifadhi triples zote zilizopo
|
||||
[ ] **Ulinganishaji wa nyuma** - Uwezo wa kurejea kwenye mpango wa zamani
|
||||
|
||||
### Mahitaji ya Uendeshaji
|
||||
[ ] **Uhamisho salama** - Uanzishaji wa kijani na bluu na uwezo wa kurejesha
|
||||
[ ] **Mazingira ya ufuatiliaji** - Metri kamili kwa operesheni za meza nyingi
|
||||
[ ] **Mazingira ya majaribio** - Mfumo wote wa maswali umejaribiwa na viwango vya utendaji
|
||||
[ ] **Nyaraka** - Mbinu zilizosasishwa za uanzishaji na uendeshaji
|
||||
|
||||
## Ratiba
|
||||
|
||||
### Awamu ya 1: Utendaji
|
||||
[ ] Andika upya `cassandra_kg.py` na mpango wa meza nyingi
|
||||
[ ] Leta operesheni za kuandika kwa wingi
|
||||
[ ] Ongeza utendaji wa tamko lililoboreshwa
|
||||
[ ] Sasisha vipimo vya kitengo
|
||||
|
||||
### Awamu ya 2: Majaribio ya Uunganisho
|
||||
[ ] Sasisha vipimo vya uunganisho
|
||||
[ ] Vipimo vya utendaji
|
||||
[ ] Majaribio ya mzigo na kiasi cha data ya kweli
|
||||
[ ] Skripti za uthibitisho wa utangamano wa data
|
||||
|
||||
### Awamu ya 3: Upangaji wa Uhamishaji
|
||||
[ ] Skripti za uanzishaji wa kijani na bluu
|
||||
[ ] Zana za uhamishaji wa data
|
||||
[ ] Sasisho za dashibodi ya ufuatiliaji
|
||||
[ ] Taratibu za kurejesha
|
||||
|
||||
### Awamu ya 4: Uanzishaji wa Uzalishaji
|
||||
[ ] Uanzishaji wa hatua kwa hatua katika uzalishaji
|
||||
[ ] Ufuatiliaji na uthibitisho wa utendaji
|
||||
[ ] Usafishaji wa meza za zamani
|
||||
[ ] Sasisho za nyaraka
|
||||
|
||||
## Hitimisho
|
||||
|
||||
Mbinu hii ya kupunguza data katika meza nyingi inashughulikia moja kwa moja matatizo mawili muhimu ya utendaji:
|
||||
|
||||
1. **Inaondoa ALLOW FILTERING iliyogharimu** kwa kutoa miundo bora ya meza kwa kila mfumo wa swali
|
||||
2. **Inaboresha ufanisi wa uwekaji** kupitia ufunguo wa pamoja wa sehemu ambazo husambaza mzigo vizuri
|
||||
|
||||
Mbinu hii inatumia nguvu za Cassandra huku ikiendelea kudumisha ulinganishaji kamili wa API, kuhakikisha kuwa msimbo uliopo unafaidika kiotomatiki kutoka kwa maboresho ya utendaji.
|
||||
687
docs/tech-specs/cassandra-performance-refactor.tr.md
Normal file
687
docs/tech-specs/cassandra-performance-refactor.tr.md
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Teknik Özellikler: Cassandra Bilgi Tabanı Performans Yenilemesi"
|
||||
parent: "Turkish (Beta)"
|
||||
---
|
||||
|
||||
# Teknik Özellikler: Cassandra Bilgi Tabanı Performans Yenilemesi
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**Durum:** Taslak
|
||||
**Yazar:** Yardımcı
|
||||
**Tarih:** 2025-09-18
|
||||
|
||||
## Genel Bakış
|
||||
|
||||
Bu özellik, TrustGraph Cassandra bilgi tabanı uygulamasındaki performans sorunlarına değinmekte ve RDF üçlü depolama ve sorgulama için optimizasyonlar önermektedir.
|
||||
|
||||
## Mevcut Uygulama
|
||||
|
||||
### Şema Tasarımı
|
||||
|
||||
Mevcut uygulama, `trustgraph-flow/trustgraph/direct/cassandra_kg.py`'da tek bir tablo tasarımı kullanmaktadır:
|
||||
|
||||
```sql
|
||||
CREATE TABLE triples (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
|
||||
**İkincil İndeksler:**
|
||||
`triples_s` ON `s` (özne)
|
||||
`triples_p` ON `p` (yüklem)
|
||||
`triples_o` ON `o` (nesne)
|
||||
|
||||
### Sorgu Desenleri
|
||||
|
||||
Mevcut uygulama, 8 farklı sorgu desenini desteklemektedir:
|
||||
|
||||
1. **get_all(collection, limit=50)** - Bir koleksiyon için tüm üçlüleri getirir.
|
||||
```sql
|
||||
SELECT s, p, o FROM triples WHERE collection = ? LIMIT 50
|
||||
```
|
||||
|
||||
2. **get_s(collection, s, limit=10)** - Konuya göre sorgulama
|
||||
```sql
|
||||
SELECT p, o FROM triples WHERE collection = ? AND s = ? LIMIT 10
|
||||
```
|
||||
|
||||
3. **get_p(collection, p, limit=10)** - Öznitelik kullanarak sorgulama
|
||||
```sql
|
||||
SELECT s, o FROM triples WHERE collection = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
4. **get_o(collection, o, limit=10)** - Nesneye göre sorgulama
|
||||
```sql
|
||||
SELECT s, p FROM triples WHERE collection = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
5. **get_sp(collection, s, p, limit=10)** - Konu + yüklem ile sorgulama
|
||||
```sql
|
||||
SELECT o FROM triples WHERE collection = ? AND s = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
6. **get_po(collection, p, o, limit=10)** - Öznitelik + nesneye göre sorgulama ⚠️
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
7. **get_os(collection, o, s, limit=10)** - Nesne + konu ile sorgulama ⚠️
|
||||
```sql
|
||||
SELECT p FROM triples WHERE collection = ? AND o = ? AND s = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
8. **get_spo(collection, s, p, o, limit=10)** - Tam üçlü eşleşme
|
||||
```sql
|
||||
SELECT s as x FROM triples WHERE collection = ? AND s = ? AND p = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
### Mevcut Mimari
|
||||
|
||||
**Dosya: `trustgraph-flow/trustgraph/direct/cassandra_kg.py`**
|
||||
Tüm işlemleri yöneten tek `KnowledgeGraph` sınıfı
|
||||
Küresel `_active_clusters` listesi aracılığıyla bağlantı havuzu
|
||||
Sabit tablo adı: `"triples"`
|
||||
Kullanıcı modeli başına keyspace
|
||||
Faktörü 1 olan SimpleStrategy replikasyonu
|
||||
|
||||
**Entegrasyon Noktaları:**
|
||||
**Yazma Yolu:** `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
**Sorgu Yolu:** `trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
**Bilgi Deposu:** `trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
|
||||
## Tespit Edilen Performans Sorunları
|
||||
|
||||
### Şema Seviyesi Sorunlar
|
||||
|
||||
1. **Verimsiz Birincil Anahtar Tasarımı**
|
||||
Mevcut: `PRIMARY KEY (collection, s, p, o)`
|
||||
Sık erişim kalıpları için zayıf kümelenmeye neden olur
|
||||
Pahalı ikincil indeks kullanımını zorlar
|
||||
|
||||
2. **İkincil İndeks Aşırı Kullanımı** ⚠️
|
||||
Yüksek kardinaliteli sütunlarda (s, p, o) üç ikincil indeks
|
||||
Cassandra'daki ikincil indeksler pahalıdır ve iyi ölçeklenmez
|
||||
6 ve 7 numaralı sorgular `ALLOW FILTERING` gerektirir, bu da zayıf veri modellemesini gösterir
|
||||
|
||||
3. **Sıcak Bölüm Riski**
|
||||
Tek bölüm anahtarı `collection`, sıcak bölümlere neden olabilir
|
||||
Büyük koleksiyonlar tek düğümlere yoğunlaşacaktır
|
||||
Yük dengeleme için dağıtım stratejisi yoktur
|
||||
|
||||
### Sorgu Seviyesi Sorunlar
|
||||
|
||||
1. **ALLOW FILTERING Kullanımı** ⚠️
|
||||
İki sorgu türü (get_po, get_os) `ALLOW FILTERING` gerektirir
|
||||
Bu sorgular birden fazla bölümü tarar ve son derece pahalıdır
|
||||
Performans, veri boyutuyla doğrusal olarak düşer
|
||||
|
||||
2. **Verimsiz Erişim Kalıpları**
|
||||
Yaygın RDF sorgu kalıpları için optimizasyon yoktur
|
||||
Sık sorgu kombinasyonları için bileşik indeksler eksiktir
|
||||
Grafik geçiş kalıpları dikkate alınmamıştır
|
||||
|
||||
3. **Sorgu Optimizasyonu Eksikliği**
|
||||
Hazırlanmış ifade önbelleği yok
|
||||
Sorgu ipuçları veya optimizasyon stratejileri yok
|
||||
Basit LIMIT'in ötesinde sayfalama dikkate alınmamıştır
|
||||
|
||||
## Problem Tanımı
|
||||
|
||||
Mevcut Cassandra bilgi tabanı uygulaması, iki kritik performans darboğazına sahiptir:
|
||||
|
||||
### 1. Verimsiz get_po Sorgusu Performansı
|
||||
|
||||
`get_po(collection, p, o)` sorgusu, `ALLOW FILTERING` gerektirdiği için son derece verimsizdir:
|
||||
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
**Neden bunun sorunlu olduğu:**
|
||||
`ALLOW FILTERING`, Cassandra'nın koleksiyon içindeki tüm bölümleri taramasını zorlar.
|
||||
Performans, veri boyutuyla doğrusal olarak düşer.
|
||||
Bu, yaygın bir RDF sorgu desenidir (belirli bir öznelik-nesne ilişkisine sahip konuları bulmak).
|
||||
Veri büyüdükçe kümede önemli bir yük oluşturur.
|
||||
|
||||
### 2. Kötü Kümeleme Stratejisi
|
||||
|
||||
Mevcut birincil anahtar `PRIMARY KEY (collection, s, p, o)`, minimum kümeleme faydası sağlar:
|
||||
|
||||
**Mevcut kümeleme ile ilgili sorunlar:**
|
||||
Bölüm anahtarı olarak `collection`, verileri etkili bir şekilde dağıtmaz.
|
||||
Çoğu koleksiyon, kümelemeyi etkisiz hale getiren çeşitli veriler içerir.
|
||||
RDF sorgularındaki yaygın erişim kalıpları dikkate alınmamıştır.
|
||||
Büyük koleksiyonlar, tek düğümlerde "sıcak" bölümler oluşturur.
|
||||
Kümeleme sütunları (s, p, o), tipik grafik geçiş kalıpları için optimize edilmemiştir.
|
||||
|
||||
**Etkisi:**
|
||||
Sorgular, veri yerelliğinden faydalanmaz.
|
||||
Kötü önbellek kullanımı.
|
||||
Küme düğümleri arasında düzensiz yük dağılımı.
|
||||
Koleksiyonlar büyüdükçe ölçeklenebilirlik darboğazları.
|
||||
|
||||
## Önerilen Çözüm: 4-Tablolu Normalizasyon Stratejisi
|
||||
|
||||
### Genel Bakış
|
||||
|
||||
Tek `triples` tablosunu, belirli sorgu kalıpları için optimize edilmiş dört özel amaçlı tabloyla değiştirin. Bu, ikincil dizinlere ve ALLOW FILTERING'e olan ihtiyacı ortadan kaldırırken, tüm sorgu türleri için optimum performans sağlar. Dördüncü tablo, bileşik bölüm anahtarlarına rağmen verimli koleksiyon silme olanağı sağlar.
|
||||
|
||||
### Yeni Şema Tasarımı
|
||||
|
||||
**Tablo 1: Konu Odaklı Sorgular (triples_s)**
|
||||
```sql
|
||||
CREATE TABLE triples_s (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY ((collection, s), p, o)
|
||||
);
|
||||
```
|
||||
**Optimize eder:** get_s, get_sp, get_os
|
||||
**Bölüm Anahtarı:** (collection, s) - Yalnızca collection'dan daha iyi dağılım sağlar
|
||||
**Kümeleme:** (p, o) - Bir konu için verimli öznelik/nesne aramalarını sağlar
|
||||
|
||||
**Tablo 2: Öznelik-Nesne Sorguları (triples_p)**
|
||||
```sql
|
||||
CREATE TABLE triples_p (
|
||||
collection text,
|
||||
p text,
|
||||
o text,
|
||||
s text,
|
||||
PRIMARY KEY ((collection, p), o, s)
|
||||
);
|
||||
```
|
||||
**Optimize eder:** get_p, get_po (ALLOW FILTERING özelliğini ortadan kaldırır!)
|
||||
**Bölüm Anahtarı:** (collection, p) - Öznitelik yoluyla doğrudan erişim
|
||||
**Kümeleme:** (o, s) - Verimli nesne-özne geçişi
|
||||
|
||||
**Tablo 3: Nesne Odaklı Sorgular (triples_o)**
|
||||
```sql
|
||||
CREATE TABLE triples_o (
|
||||
collection text,
|
||||
o text,
|
||||
s text,
|
||||
p text,
|
||||
PRIMARY KEY ((collection, o), s, p)
|
||||
);
|
||||
```
|
||||
**Optimize eder:** get_o
|
||||
**Bölüm Anahtarı:** (collection, o) - Nesneye doğrudan erişim
|
||||
**Kümeleme:** (s, p) - Verimli özne-yüklem geçişi
|
||||
|
||||
**Tablo 4: Koleksiyon Yönetimi ve SPO Sorguları (triples_collection)**
|
||||
```sql
|
||||
CREATE TABLE triples_collection (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
**Optimize eder:** get_spo, delete_collection
|
||||
**Bölüm Anahtarı:** sadece koleksiyon - Verimli koleksiyon seviyesindeki işlemleri sağlar.
|
||||
**Kümeleme:** (s, p, o) - Standart üçlü sıralama
|
||||
**Amaç:** Hem tam SPO aramaları için hem de silme indeksi olarak çift amaçlı kullanım.
|
||||
|
||||
### Sorgu Eşlemesi
|
||||
|
||||
| Orijinal Sorgu | Hedef Tablo | Performans İyileştirmesi |
|
||||
|----------------|-------------|------------------------|
|
||||
| get_all(collection) | triples_s | FİLTRELEME İZNİ VERİLEBİLİR (taramaya uygun) |
|
||||
| get_s(collection, s) | triples_s | Doğrudan bölüm erişimi |
|
||||
| get_p(collection, p) | triples_p | Doğrudan bölüm erişimi |
|
||||
| get_o(collection, o) | triples_o | Doğrudan bölüm erişimi |
|
||||
| get_sp(collection, s, p) | triples_s | Bölüm + kümeleme |
|
||||
| get_po(collection, p, o) | triples_p | **Artık FİLTRELEME İZNİ YOK!** |
|
||||
| get_os(collection, o, s) | triples_o | Bölüm + kümeleme |
|
||||
| get_spo(collection, s, p, o) | triples_collection | Tam anahtar araması |
|
||||
| delete_collection(collection) | triples_collection | İndeksi oku, tümünü toplu olarak sil |
|
||||
|
||||
### Koleksiyon Silme Stratejisi
|
||||
|
||||
Birleşik bölüm anahtarlarıyla, `DELETE FROM table WHERE collection = ?`'ı doğrudan çalıştıramayız. Bunun yerine:
|
||||
|
||||
1. **Okuma Aşaması:** Tüm üçlüleri saymak için `triples_collection` sorgusunu kullanın:
|
||||
```sql
|
||||
SELECT s, p, o FROM triples_collection WHERE collection = ?
|
||||
```
|
||||
Bu, `collection`'ın bu tablo için bölümleme anahtarı olması nedeniyle verimlidir.
|
||||
|
||||
2. **Silme Aşaması:** Her (s, p, o) üçlüsü için, tüm 4 tablodan, tam bölümleme anahtarlarını kullanarak silin:
|
||||
```sql
|
||||
DELETE FROM triples_s WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
DELETE FROM triples_p WHERE collection = ? AND p = ? AND o = ? AND s = ?
|
||||
DELETE FROM triples_o WHERE collection = ? AND o = ? AND s = ? AND p = ?
|
||||
DELETE FROM triples_collection WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
```
|
||||
Verimlilik için 100'lük gruplar halinde işlenir.
|
||||
|
||||
**Ayrılık Analizi:**
|
||||
✅ Dağıtılmış bölümlerle optimum sorgu performansını korur.
|
||||
✅ Büyük koleksiyonlar için "sıcak" bölümler yoktur.
|
||||
❌ Daha karmaşık silme mantığı (okuyup sonra sil).
|
||||
❌ Silme süresi, koleksiyon boyutuna orantılıdır.
|
||||
|
||||
### Avantajlar
|
||||
|
||||
1. **ALLOW FILTERING'i ortadan kaldırır** - Her sorgunun optimum bir erişim yolu vardır (get_all taraması hariç).
|
||||
2. **İkincil İndeks Yok** - Her tablo, kendi sorgu deseninin indeksidir.
|
||||
3. **Daha İyi Veri Dağılımı** - Bileşik bölüm anahtarları, yükü etkili bir şekilde dağıtır.
|
||||
4. **Öngörülebilir Performans** - Sorgu süresi, toplam veriye değil, sonuç boyutuna orantılıdır.
|
||||
5. **Cassandra'nın Güçlerinden Yararlanır** - Cassandra'nın mimarisi için tasarlanmıştır.
|
||||
6. **Koleksiyon Silme İşlemini Etkinleştirir** - triples_collection, silme indeksi olarak hizmet eder.
|
||||
|
||||
## Uygulama Planı
|
||||
|
||||
### Değiştirilmesi Gereken Dosyalar
|
||||
|
||||
#### Birincil Uygulama Dosyası
|
||||
|
||||
**`trustgraph-flow/trustgraph/direct/cassandra_kg.py`** - Tamamen yeniden yazılması gerekir.
|
||||
|
||||
**Yeniden Düzenlenmesi Gereken Mevcut Yöntemler:**
|
||||
```python
|
||||
# Schema initialization
|
||||
def init(self) -> None # Replace single table with three tables
|
||||
|
||||
# Insert operations
|
||||
def insert(self, collection, s, p, o) -> None # Write to all three tables
|
||||
|
||||
# Query operations (API unchanged, implementation optimized)
|
||||
def get_all(self, collection, limit=50) # Use triples_by_subject
|
||||
def get_s(self, collection, s, limit=10) # Use triples_by_subject
|
||||
def get_p(self, collection, p, limit=10) # Use triples_by_po
|
||||
def get_o(self, collection, o, limit=10) # Use triples_by_object
|
||||
def get_sp(self, collection, s, p, limit=10) # Use triples_by_subject
|
||||
def get_po(self, collection, p, o, limit=10) # Use triples_by_po (NO ALLOW FILTERING!)
|
||||
def get_os(self, collection, o, s, limit=10) # Use triples_by_subject
|
||||
def get_spo(self, collection, s, p, o, limit=10) # Use triples_by_subject
|
||||
|
||||
# Collection management
|
||||
def delete_collection(self, collection) -> None # Delete from all three tables
|
||||
```
|
||||
|
||||
#### Entegrasyon Dosyaları (Herhangi Bir Mantıksal Değişiklik Gerekmiyor)
|
||||
|
||||
**`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`**
|
||||
Herhangi bir değişiklik gerekmiyor - mevcut KnowledgeGraph API'sini kullanır.
|
||||
Performans iyileştirmelerinden otomatik olarak faydalanır.
|
||||
|
||||
**`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`**
|
||||
Herhangi bir değişiklik gerekmiyor - mevcut KnowledgeGraph API'sini kullanır.
|
||||
Performans iyileştirmelerinden otomatik olarak faydalanır.
|
||||
|
||||
### Güncelleme Gerektiren Test Dosyaları
|
||||
|
||||
#### Birim Testleri
|
||||
**`tests/unit/test_storage/test_triples_cassandra_storage.py`**
|
||||
Şema değişiklikleri için test beklentilerini güncelleyin.
|
||||
Çok tablolu tutarlılık için testler ekleyin.
|
||||
Sorgu planlarında ALLOW FILTERING kullanımını doğrulayın.
|
||||
|
||||
**`tests/unit/test_query/test_triples_cassandra_query.py`**
|
||||
Performans doğrulama ifadelerini güncelleyin.
|
||||
Tüm 8 sorgu desenini yeni tablolara karşı test edin.
|
||||
Sorgu yönlendirmesinin doğru tablolara yapıldığını doğrulayın.
|
||||
|
||||
#### Entegrasyon Testleri
|
||||
**`tests/integration/test_cassandra_integration.py`**
|
||||
Yeni şemayla uçtan uca testler.
|
||||
Performans karşılaştırma ölçümleri.
|
||||
Tablolar arasındaki veri tutarlılığının doğrulanması.
|
||||
|
||||
**`tests/unit/test_storage/test_cassandra_config_integration.py`**
|
||||
Şema doğrulama testlerini güncelleyin.
|
||||
Geçiş senaryolarını test edin.
|
||||
|
||||
### Uygulama Stratejisi
|
||||
|
||||
#### 1. Aşama: Şema ve Temel Yöntemler
|
||||
1. **`init()` yöntemini yeniden yazın** - Dört tablo oluşturun, bir yerine.
|
||||
2. **`insert()` yöntemini yeniden yazın** - Tüm dört tabloya toplu yazma işlemleri.
|
||||
3. **Hazırlanmış ifadeleri uygulayın** - Optimum performans için.
|
||||
4. **Tablo yönlendirme mantığını ekleyin** - Sorguları en uygun tablolara yönlendirin.
|
||||
5. **Toplu silme işlemini uygulayın** - triples_collection'dan okuyun, tüm tablolardan toplu olarak silin.
|
||||
|
||||
#### 2. Aşama: Sorgu Yöntemi Optimizasyonu
|
||||
1. **Her get_* yöntemini yeniden yazın** - En uygun tabloyu kullanmak için.
|
||||
2. **Tüm ALLOW FILTERING kullanımını kaldırın**.
|
||||
3. **Verimli kümeleme anahtar kullanımı uygulayın**.
|
||||
4. **Sorgu performansını kaydetme özelliğini ekleyin**.
|
||||
|
||||
#### 3. Aşama: Koleksiyon Yönetimi
|
||||
1. **`delete_collection()`'ı güncelleyin** - Tüm üç tablodan kaldırın.
|
||||
2. **Tutarlılık doğrulamasını ekleyin** - Tüm tabloların senkronize kalmasını sağlayın.
|
||||
3. **Toplu işlemleri uygulayın** - Atomik çok tablolu işlemler için.
|
||||
|
||||
### Önemli Uygulama Detayları
|
||||
|
||||
#### Toplu Yazma Stratejisi
|
||||
```python
|
||||
def insert(self, collection, s, p, o):
|
||||
batch = BatchStatement()
|
||||
|
||||
# Insert into all four tables
|
||||
batch.add(self.insert_subject_stmt, (collection, s, p, o))
|
||||
batch.add(self.insert_po_stmt, (collection, p, o, s))
|
||||
batch.add(self.insert_object_stmt, (collection, o, s, p))
|
||||
batch.add(self.insert_collection_stmt, (collection, s, p, o))
|
||||
|
||||
self.session.execute(batch)
|
||||
```
|
||||
|
||||
#### Sorgu Yönlendirme Mantığı
|
||||
```python
|
||||
def get_po(self, collection, p, o, limit=10):
|
||||
# Route to triples_p table - NO ALLOW FILTERING!
|
||||
return self.session.execute(
|
||||
self.get_po_stmt,
|
||||
(collection, p, o, limit)
|
||||
)
|
||||
|
||||
def get_spo(self, collection, s, p, o, limit=10):
|
||||
# Route to triples_collection table for exact SPO lookup
|
||||
return self.session.execute(
|
||||
self.get_spo_stmt,
|
||||
(collection, s, p, o, limit)
|
||||
)
|
||||
```
|
||||
|
||||
#### Koleksiyon Silme Mantığı
|
||||
```python
|
||||
def delete_collection(self, collection):
|
||||
# Step 1: Read all triples from collection table
|
||||
rows = self.session.execute(
|
||||
f"SELECT s, p, o FROM {self.collection_table} WHERE collection = %s",
|
||||
(collection,)
|
||||
)
|
||||
|
||||
# Step 2: Batch delete from all 4 tables
|
||||
batch = BatchStatement()
|
||||
count = 0
|
||||
|
||||
for row in rows:
|
||||
s, p, o = row.s, row.p, row.o
|
||||
|
||||
# Delete using full partition keys for each table
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.subject_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.po_table} WHERE collection = ? AND p = ? AND o = ? AND s = ?"
|
||||
), (collection, p, o, s))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.object_table} WHERE collection = ? AND o = ? AND s = ? AND p = ?"
|
||||
), (collection, o, s, p))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.collection_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
count += 1
|
||||
|
||||
# Execute every 100 triples to avoid oversized batches
|
||||
if count % 100 == 0:
|
||||
self.session.execute(batch)
|
||||
batch = BatchStatement()
|
||||
|
||||
# Execute remaining deletions
|
||||
if count % 100 != 0:
|
||||
self.session.execute(batch)
|
||||
|
||||
logger.info(f"Deleted {count} triples from collection {collection}")
|
||||
```
|
||||
|
||||
#### Hazırlanmış İfade Optimizasyonu
|
||||
```python
|
||||
def prepare_statements(self):
|
||||
# Cache prepared statements for better performance
|
||||
self.insert_subject_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.subject_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_po_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.po_table} (collection, p, o, s) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_object_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.object_table} (collection, o, s, p) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_collection_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.collection_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
# ... query statements
|
||||
```
|
||||
|
||||
## Göç Stratejisi
|
||||
|
||||
### Veri Göç Yaklaşımı
|
||||
|
||||
#### Seçenek 1: Mavi-Yeşil Dağıtım (Önerilen)
|
||||
1. **Yeni şemayı mevcut olanın yanında dağıtın** - Geçici olarak farklı tablo adları kullanın
|
||||
2. **Çift yazma dönemi** - Geçiş sırasında hem eski hem de yeni şemalara yazın
|
||||
3. **Arka planda veri taşıma** - Mevcut verileri yeni tablolara kopyalayın
|
||||
4. **Okuma yönlendirmesini değiştirin** - Veriler taşındıktan sonra sorguları yeni tablolara yönlendirin
|
||||
5. **Eski tabloları kaldırın** - Doğrulama süresinden sonra
|
||||
|
||||
#### Seçenek 2: Yerinde Göç
|
||||
1. **Şema ekleme** - Yeni tabloları mevcut anahtar uzayında oluşturun
|
||||
2. **Veri taşıma betiği** - Eski tablodan yeni tablolara toplu olarak veri kopyalayın
|
||||
3. **Uygulama güncellemesi** - Göç tamamlandıktan sonra yeni kodu dağıtın
|
||||
4. **Eski tablo temizliği** - Eski tabloyu ve indeksleri kaldırın
|
||||
|
||||
### Geriye Dönük Uyumluluk
|
||||
|
||||
#### Dağıtım Stratejisi
|
||||
```python
|
||||
# Environment variable to control table usage during migration
|
||||
USE_LEGACY_TABLES = os.getenv('CASSANDRA_USE_LEGACY', 'false').lower() == 'true'
|
||||
|
||||
class KnowledgeGraph:
|
||||
def __init__(self, ...):
|
||||
if USE_LEGACY_TABLES:
|
||||
self.init_legacy_schema()
|
||||
else:
|
||||
self.init_optimized_schema()
|
||||
```
|
||||
|
||||
#### Göç Script'i
|
||||
```python
|
||||
def migrate_data():
|
||||
# Read from old table
|
||||
old_triples = session.execute("SELECT collection, s, p, o FROM triples")
|
||||
|
||||
# Batch write to new tables
|
||||
for batch in batched(old_triples, 100):
|
||||
batch_stmt = BatchStatement()
|
||||
for row in batch:
|
||||
# Add to all three new tables
|
||||
batch_stmt.add(insert_subject_stmt, row)
|
||||
batch_stmt.add(insert_po_stmt, (row.collection, row.p, row.o, row.s))
|
||||
batch_stmt.add(insert_object_stmt, (row.collection, row.o, row.s, row.p))
|
||||
session.execute(batch_stmt)
|
||||
```
|
||||
|
||||
### Doğrulama Stratejisi
|
||||
|
||||
#### Veri Tutarlılık Kontrolleri
|
||||
```python
|
||||
def validate_migration():
|
||||
# Count total records in old vs new tables
|
||||
old_count = session.execute("SELECT COUNT(*) FROM triples WHERE collection = ?", (collection,))
|
||||
new_count = session.execute("SELECT COUNT(*) FROM triples_by_subject WHERE collection = ?", (collection,))
|
||||
|
||||
assert old_count == new_count, f"Record count mismatch: {old_count} vs {new_count}"
|
||||
|
||||
# Spot check random samples
|
||||
sample_queries = generate_test_queries()
|
||||
for query in sample_queries:
|
||||
old_result = execute_legacy_query(query)
|
||||
new_result = execute_optimized_query(query)
|
||||
assert old_result == new_result, f"Query results differ for {query}"
|
||||
```
|
||||
|
||||
## Test Stratejisi
|
||||
|
||||
### Performans Testi
|
||||
|
||||
#### Benchmark Senaryoları
|
||||
1. **Sorgu Performansı Karşılaştırması**
|
||||
Tüm 8 sorgu türü için performans metrikleri (önce/sonra)
|
||||
get_po performans iyileştirmesine odaklanın (ALLOW FILTERING'i kaldırın)
|
||||
Çeşitli veri boyutları altında sorgu gecikmesini ölçün
|
||||
|
||||
2. **Yük Testi**
|
||||
Eşzamanlı sorgu yürütme
|
||||
Toplu işlemlerle yazma hızı
|
||||
Bellek ve CPU kullanımı
|
||||
|
||||
3. **Ölçeklenebilirlik Testi**
|
||||
Artan koleksiyon boyutlarıyla performans
|
||||
Çoklu koleksiyon sorgu dağıtımı
|
||||
Küme düğümü kullanımı
|
||||
|
||||
#### Test Veri Kümeleri
|
||||
**Küçük:** Koleksiyon başına 10K üçlü
|
||||
**Orta:** Koleksiyon başına 100K üçlü
|
||||
**Büyük:** Koleksiyon başına 1M+ üçlü
|
||||
**Çoklu koleksiyonlar:** Test bölüm dağıtımı
|
||||
|
||||
### Fonksiyonel Test
|
||||
|
||||
#### Birim Testi Güncellemeleri
|
||||
```python
|
||||
# Example test structure for new implementation
|
||||
class TestCassandraKGPerformance:
|
||||
def test_get_po_no_allow_filtering(self):
|
||||
# Verify get_po queries don't use ALLOW FILTERING
|
||||
with patch('cassandra.cluster.Session.execute') as mock_execute:
|
||||
kg.get_po('test_collection', 'predicate', 'object')
|
||||
executed_query = mock_execute.call_args[0][0]
|
||||
assert 'ALLOW FILTERING' not in executed_query
|
||||
|
||||
def test_multi_table_consistency(self):
|
||||
# Verify all tables stay in sync
|
||||
kg.insert('test', 's1', 'p1', 'o1')
|
||||
|
||||
# Check all tables contain the triple
|
||||
assert_triple_exists('triples_by_subject', 'test', 's1', 'p1', 'o1')
|
||||
assert_triple_exists('triples_by_po', 'test', 'p1', 'o1', 's1')
|
||||
assert_triple_exists('triples_by_object', 'test', 'o1', 's1', 'p1')
|
||||
```
|
||||
|
||||
#### Entegrasyon Testi Güncellemeleri
|
||||
```python
|
||||
class TestCassandraIntegration:
|
||||
def test_query_performance_regression(self):
|
||||
# Ensure new implementation is faster than old
|
||||
old_time = benchmark_legacy_get_po()
|
||||
new_time = benchmark_optimized_get_po()
|
||||
assert new_time < old_time * 0.5 # At least 50% improvement
|
||||
|
||||
def test_end_to_end_workflow(self):
|
||||
# Test complete write -> query -> delete cycle
|
||||
# Verify no performance degradation in integration
|
||||
```
|
||||
|
||||
### Geri Alma Planı
|
||||
|
||||
#### Hızlı Geri Alma Stratejisi
|
||||
1. **Ortam değişkeni geçişi** - Eski tablolara hemen geri dönün.
|
||||
2. **Eski tablolara devam edin** - Performans kanıtlanana kadar silmeyin.
|
||||
3. **İzleme uyarıları** - Hata oranlarına/gecikmelere göre otomatik geri alma tetikleyicileri.
|
||||
|
||||
#### Geri Alma Doğrulama
|
||||
```python
|
||||
def rollback_to_legacy():
|
||||
# Set environment variable
|
||||
os.environ['CASSANDRA_USE_LEGACY'] = 'true'
|
||||
|
||||
# Restart services to pick up change
|
||||
restart_cassandra_services()
|
||||
|
||||
# Validate functionality
|
||||
run_smoke_tests()
|
||||
```
|
||||
|
||||
## Riskler ve Dikkat Edilmesi Gerekenler
|
||||
|
||||
### Performans Riskleri
|
||||
**Yazma gecikmesi artışı** - Her eklemeye 4 yazma işlemi (3 tablolu yaklaşıma göre %33 daha fazla)
|
||||
**Depolama alanı kullanımı** - 4 kat daha fazla depolama alanı gereksinimi (3 tablolu yaklaşıma göre %33 daha fazla)
|
||||
**Toplu yazma hataları** - Uygun hata yönetimi gereklidir
|
||||
**Silme karmaşıklığı** - Koleksiyon silme işlemi, okuma-sonra-silme döngüsü gerektirir
|
||||
|
||||
### İşletim Riskleri
|
||||
**Geçiş karmaşıklığı** - Büyük veri kümeleri için veri geçişi
|
||||
**Tutarlılık sorunları** - Tüm tabloların senkronize olduğundan emin olmak
|
||||
**İzleme eksiklikleri** - Çok tablolu işlemler için yeni metrikler gereklidir
|
||||
|
||||
### Azaltma Stratejileri
|
||||
1. **Aşamalı dağıtım** - Küçük koleksiyonlarla başlayın
|
||||
2. **Kapsamlı izleme** - Tüm performans metriklerini takip edin
|
||||
3. **Otomatik doğrulama** - Sürekli tutarlılık kontrolü
|
||||
4. **Hızlı geri alma yeteneği** - Ortam tabanlı tablo seçimi
|
||||
|
||||
## Başarı Kriterleri
|
||||
|
||||
### Performans İyileştirmeleri
|
||||
[ ] **ALLOW FILTERING'i ortadan kaldırın** - get_po ve get_os sorguları filtreleme olmadan çalışır
|
||||
[ ] **Sorgu gecikmesi azaltma** - Sorgu yanıt sürelerinde %50 veya daha fazla iyileşme
|
||||
[ ] **Daha iyi yük dağılımı** - Hiçbir "sıcak" bölüm yok, küme düğümleri arasında eşit yük dağılımı
|
||||
[ ] **Ölçeklenebilir performans** - Sorgu süresi, toplam veri miktarı yerine sonuç büyüklüğüne orantılı
|
||||
|
||||
### Fonksiyonel Gereksinimler
|
||||
[ ] **API uyumluluğu** - Tüm mevcut kod, herhangi bir değişiklik olmadan çalışmaya devam eder
|
||||
[ ] **Veri tutarlılığı** - Tüm üç tablo senkronize kalır
|
||||
[ ] **Sıfır veri kaybı** - Geçiş, tüm mevcut üçlüleri korur
|
||||
[ ] **Geriye dönme uyumluluğu** - Eski şemaya geri dönme yeteneği
|
||||
|
||||
### İşletim Gereksinimleri
|
||||
[ ] **Güvenli geçiş** - Geri alma yeteneği olan mavi-yeşil dağıtım
|
||||
[ ] **İzleme kapsamı** - Çok tablolu işlemler için kapsamlı metrikler
|
||||
[ ] **Test kapsamı** - Tüm sorgu kalıpları, performans kıyaslamalarıyla test edilmiştir
|
||||
[ ] **Belgeleme** - Güncellenmiş dağıtım ve işletim prosedürleri
|
||||
|
||||
## Zaman Çizelgesi
|
||||
|
||||
### 1. Aşama: Uygulama
|
||||
[ ] `cassandra_kg.py`'ı çok tablolu şemayla yeniden yazın
|
||||
[ ] Toplu yazma işlemlerini uygulayın
|
||||
[ ] Hazırlanmış ifade optimizasyonunu ekleyin
|
||||
[ ] Birim testlerini güncelleyin
|
||||
|
||||
### 2. Aşama: Entegrasyon Testi
|
||||
[ ] Entegrasyon testlerini güncelleyin
|
||||
[ ] Performans kıyaslaması
|
||||
[ ] Gerçekçi veri hacimleriyle yük testi
|
||||
[ ] Veri tutarlılığı için doğrulama betikleri
|
||||
|
||||
### 3. Aşama: Geçiş Planlaması
|
||||
[ ] Mavi-yeşil dağıtım betikleri
|
||||
[ ] Veri geçiş araçları
|
||||
[ ] İzleme panosu güncellemeleri
|
||||
[ ] Geri alma prosedürleri
|
||||
|
||||
### 4. Aşama: Üretim Dağıtımı
|
||||
[ ] Üretime aşamalı dağıtım
|
||||
[ ] Performans izleme ve doğrulama
|
||||
[ ] Eski tabloların temizlenmesi
|
||||
[ ] Belgeleme güncellemeleri
|
||||
|
||||
## Sonuç
|
||||
|
||||
Bu çok tablolu normalleştirme stratejisi, doğrudan iki kritik performans darboğazını ele almaktadır:
|
||||
|
||||
1. **Pahalı ALLOW FILTERING'i ortadan kaldırır** ve her sorgu kalıbı için optimum tablo yapıları sağlar.
|
||||
2. **Kompozit bölüm anahtarları aracılığıyla kümeleme etkinliğini artırır** ve yükü düzgün bir şekilde dağıtır.
|
||||
|
||||
Bu yaklaşım, Cassandra'nın güçlü yönlerinden yararlanırken, mevcut kodun performans iyileştirmelerinden otomatik olarak yararlanmasını sağlayan tam API uyumluluğunu korur.
|
||||
687
docs/tech-specs/cassandra-performance-refactor.zh-cn.md
Normal file
687
docs/tech-specs/cassandra-performance-refactor.zh-cn.md
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
---
|
||||
layout: default
|
||||
title: "技术规范:Cassandra 知识库性能重构"
|
||||
parent: "Chinese (Beta)"
|
||||
---
|
||||
|
||||
# 技术规范:Cassandra 知识库性能重构
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
**状态:** 草稿
|
||||
**作者:** 助理
|
||||
**日期:** 2025-09-18
|
||||
|
||||
## 概述
|
||||
|
||||
本规范解决了 TrustGraph Cassandra 知识库实现中的性能问题,并提出了针对 RDF 三元组存储和查询的优化方案。
|
||||
|
||||
## 当前实现
|
||||
|
||||
### 模式设计
|
||||
|
||||
当前实现使用单表设计,位于 `trustgraph-flow/trustgraph/direct/cassandra_kg.py`:
|
||||
|
||||
```sql
|
||||
CREATE TABLE triples (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
|
||||
**次级索引:**
|
||||
`triples_s` ON `s` (主语)
|
||||
`triples_p` ON `p` (谓语)
|
||||
`triples_o` ON `o` (宾语)
|
||||
|
||||
### 查询模式
|
||||
|
||||
当前实现支持 8 种不同的查询模式:
|
||||
|
||||
1. **get_all(collection, limit=50)** - 检索集合中的所有三元组
|
||||
```sql
|
||||
SELECT s, p, o FROM triples WHERE collection = ? LIMIT 50
|
||||
```
|
||||
|
||||
2. **get_s(collection, s, limit=10)** - 通过主题进行查询
|
||||
```sql
|
||||
SELECT p, o FROM triples WHERE collection = ? AND s = ? LIMIT 10
|
||||
```
|
||||
|
||||
3. **get_p(collection, p, limit=10)** - 通过谓词进行查询
|
||||
```sql
|
||||
SELECT s, o FROM triples WHERE collection = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
4. **get_o(collection, o, limit=10)** - 通过对象查询
|
||||
```sql
|
||||
SELECT s, p FROM triples WHERE collection = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
5. **get_sp(collection, s, p, limit=10)** - 通过主语 + 谓语进行查询。
|
||||
```sql
|
||||
SELECT o FROM triples WHERE collection = ? AND s = ? AND p = ? LIMIT 10
|
||||
```
|
||||
|
||||
6. **get_po(collection, p, o, limit=10)** - 通过谓词 + 对象进行查询 ⚠️
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
7. **get_os(collection, o, s, limit=10)** - 通过对象 + 主题进行查询 ⚠️
|
||||
```sql
|
||||
SELECT p FROM triples WHERE collection = ? AND o = ? AND s = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
8. **get_spo(collection, s, p, o, limit=10)** - 精确三元组匹配
|
||||
```sql
|
||||
SELECT s as x FROM triples WHERE collection = ? AND s = ? AND p = ? AND o = ? LIMIT 10
|
||||
```
|
||||
|
||||
### 当前架构
|
||||
|
||||
**文件: `trustgraph-flow/trustgraph/direct/cassandra_kg.py`**
|
||||
单个 `KnowledgeGraph` 类处理所有操作
|
||||
通过全局 `_active_clusters` 列表进行连接池管理
|
||||
固定的表名: `"triples"`
|
||||
每个用户模型的 keyspace
|
||||
复制策略为 SimpleStrategy,因子为 1
|
||||
|
||||
**集成点:**
|
||||
**写入路径:** `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
**查询路径:** `trustgraph-flow/trustgraph/query/triples/cassandra/service.py`
|
||||
**知识存储:** `trustgraph-flow/trustgraph/tables/knowledge.py`
|
||||
|
||||
## 识别出的性能问题
|
||||
|
||||
### 模式层级问题
|
||||
|
||||
1. **低效的主键设计**
|
||||
当前: `PRIMARY KEY (collection, s, p, o)`
|
||||
导致常见访问模式下的聚类效果不佳
|
||||
强制使用昂贵的二级索引
|
||||
|
||||
2. **过度使用二级索引** ⚠️
|
||||
在高基数列(s, p, o)上使用了三个二级索引
|
||||
Cassandra 中的二级索引很昂贵,并且扩展性较差
|
||||
查询 6 和 7 需要 `ALLOW FILTERING`,表明数据建模存在问题
|
||||
|
||||
3. **分区热点风险**
|
||||
单个分区键 `collection` 可能会创建分区热点
|
||||
大型集合会集中在单个节点上
|
||||
没有用于负载均衡的分布策略
|
||||
|
||||
### 查询层级问题
|
||||
|
||||
1. **ALLOW FILTERING 的使用** ⚠️
|
||||
两种查询类型(get_po, get_os)需要 `ALLOW FILTERING`
|
||||
这些查询会扫描多个分区,并且非常昂贵
|
||||
性能会随着数据量的增加而线性下降
|
||||
|
||||
2. **低效的访问模式**
|
||||
没有针对常见的 RDF 查询模式进行优化
|
||||
缺少用于频繁查询组合的复合索引
|
||||
没有考虑图遍历模式
|
||||
|
||||
3. **缺乏查询优化**
|
||||
没有预处理语句缓存
|
||||
没有查询提示或优化策略
|
||||
没有考虑简单的 LIMIT 之外的分页
|
||||
|
||||
## 问题陈述
|
||||
|
||||
当前的 Cassandra 知识库实现存在两个关键的性能瓶颈:
|
||||
|
||||
### 1. get_po 查询性能低效
|
||||
|
||||
`get_po(collection, p, o)` 查询非常低效,因为它需要 `ALLOW FILTERING`:
|
||||
|
||||
```sql
|
||||
SELECT s FROM triples WHERE collection = ? AND p = ? AND o = ? LIMIT 10 ALLOW FILTERING
|
||||
```
|
||||
|
||||
**问题所在:**
|
||||
`ALLOW FILTERING` 迫使 Cassandra 扫描集合中的所有分区。
|
||||
性能会随着数据量的线性增长而下降。
|
||||
这是一个常见的 RDF 查询模式(查找具有特定谓词-对象关系的实体)。
|
||||
随着数据增长,这会在集群上产生显著的负载。
|
||||
|
||||
### 2. 聚类策略不佳
|
||||
|
||||
当前主键 `PRIMARY KEY (collection, s, p, o)` 提供的聚类优势有限:
|
||||
|
||||
**当前聚类的存在问题:**
|
||||
将 `collection` 作为分区键,无法有效分布数据。
|
||||
大多数集合包含各种数据,这使得聚类无效。
|
||||
未考虑 RDF 查询中的常见访问模式。
|
||||
大型集合会在单个节点上创建热点分区。
|
||||
聚类列 (s, p, o) 未针对典型的图遍历模式进行优化。
|
||||
|
||||
**影响:**
|
||||
查询无法受益于数据局部性。
|
||||
缓存利用率低下。
|
||||
集群节点上的负载分布不均匀。
|
||||
随着集合的增长,会出现可扩展性瓶颈。
|
||||
|
||||
## 建议的解决方案:4 表反规范化策略
|
||||
|
||||
### 概述
|
||||
|
||||
用四个专门设计的表替换单个 `triples` 表,每个表针对特定的查询模式进行了优化。 这消除了对辅助索引和 ALLOW FILTERING 的需求,同时为所有类型的查询提供最佳性能。 第四个表实现了在复合分区键下高效地删除集合的功能。
|
||||
|
||||
### 新的模式设计
|
||||
|
||||
**表 1:以实体为中心的查询 (triples_s)**
|
||||
```sql
|
||||
CREATE TABLE triples_s (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY ((collection, s), p, o)
|
||||
);
|
||||
```
|
||||
**优化:** get_s, get_sp, get_os
|
||||
**分区键:** (collection, s) - 比仅使用 collection 的分区方式分布更好
|
||||
**聚类:** (p, o) - 允许对主语进行高效的谓词/对象查找
|
||||
|
||||
**表 2:谓词-对象查询 (triples_p)**
|
||||
```sql
|
||||
CREATE TABLE triples_p (
|
||||
collection text,
|
||||
p text,
|
||||
o text,
|
||||
s text,
|
||||
PRIMARY KEY ((collection, p), o, s)
|
||||
);
|
||||
```
|
||||
**优化:** get_p, get_po (消除 ALLOW FILTERING!)
|
||||
**分区键:** (collection, p) - 通过谓词直接访问
|
||||
**聚类:** (o, s) - 高效的对象-主体遍历
|
||||
|
||||
**表 3:面向对象的查询 (triples_o)**
|
||||
```sql
|
||||
CREATE TABLE triples_o (
|
||||
collection text,
|
||||
o text,
|
||||
s text,
|
||||
p text,
|
||||
PRIMARY KEY ((collection, o), s, p)
|
||||
);
|
||||
```
|
||||
**优化:** get_o
|
||||
**分区键:** (collection, o) - 通过对象直接访问
|
||||
**聚类:** (s, p) - 高效的主体-谓语遍历
|
||||
|
||||
**表 4:集合管理与 SPO 查询 (triples_collection)**
|
||||
```sql
|
||||
CREATE TABLE triples_collection (
|
||||
collection text,
|
||||
s text,
|
||||
p text,
|
||||
o text,
|
||||
PRIMARY KEY (collection, s, p, o)
|
||||
);
|
||||
```
|
||||
**优化:** get_spo, delete_collection
|
||||
**分区键:** 仅限集合 - 启用高效的集合级别操作
|
||||
**聚类:** (s, p, o) - 标准三元组排序
|
||||
**目的:** 既用于精确的SPO查找,也用作删除索引
|
||||
|
||||
### 查询映射
|
||||
|
||||
| 原始查询 | 目标表 | 性能提升 |
|
||||
|----------------|-------------|------------------------|
|
||||
| get_all(collection) | triples_s | 允许过滤 (对于扫描是可以接受的) |
|
||||
| get_s(collection, s) | triples_s | 直接分区访问 |
|
||||
| get_p(collection, p) | triples_p | 直接分区访问 |
|
||||
| get_o(collection, o) | triples_o | 直接分区访问 |
|
||||
| get_sp(collection, s, p) | triples_s | 分区 + 聚类 |
|
||||
| get_po(collection, p, o) | triples_p | **不再需要 ALLOW FILTERING!** |
|
||||
| get_os(collection, o, s) | triples_o | 分区 + 聚类 |
|
||||
| get_spo(collection, s, p, o) | triples_collection | 精确键查找 |
|
||||
| delete_collection(collection) | triples_collection | 读取索引,批量删除所有 |
|
||||
|
||||
### 集合删除策略
|
||||
|
||||
对于复合分区键,我们不能简单地执行 `DELETE FROM table WHERE collection = ?`。 而是:
|
||||
|
||||
1. **读取阶段:** 查询 `triples_collection` 以枚举所有三元组:
|
||||
```sql
|
||||
SELECT s, p, o FROM triples_collection WHERE collection = ?
|
||||
```
|
||||
这很高效,因为 `collection` 是此表的分割键。
|
||||
|
||||
2. **删除阶段:** 对于每个三元组 (s, p, o),使用完整的分割键从所有 4 个表中删除数据。
|
||||
```sql
|
||||
DELETE FROM triples_s WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
DELETE FROM triples_p WHERE collection = ? AND p = ? AND o = ? AND s = ?
|
||||
DELETE FROM triples_o WHERE collection = ? AND o = ? AND s = ? AND p = ?
|
||||
DELETE FROM triples_collection WHERE collection = ? AND s = ? AND p = ? AND o = ?
|
||||
```
|
||||
批量处理,每次100个,以提高效率。
|
||||
|
||||
**权衡分析:**
|
||||
✅ 保持最佳查询性能,采用分布式分区。
|
||||
✅ 大型集合不会出现热点分区。
|
||||
❌ 删除逻辑更复杂(先读取,再删除)。
|
||||
❌ 删除时间与集合大小成正比。
|
||||
|
||||
### 优点
|
||||
|
||||
1. **消除 ALLOW FILTERING** - 每个查询都有最佳访问路径(除了全表扫描)。
|
||||
2. **无需二级索引** - 每个表本身就是其查询模式的索引。
|
||||
3. **更好的数据分布** - 组合分区键能有效分散负载。
|
||||
4. **可预测的性能** - 查询时间与结果大小成正比,而不是总数据量。
|
||||
5. **利用 Cassandra 的优势** - 专为 Cassandra 的架构设计。
|
||||
6. **支持集合删除** - `triples_collection` 作为删除索引。
|
||||
|
||||
## 实施计划
|
||||
|
||||
### 需要修改的文件
|
||||
|
||||
#### 主要实施文件
|
||||
|
||||
**`trustgraph-flow/trustgraph/direct/cassandra_kg.py`** - 需要完全重写。
|
||||
|
||||
**需要重构的现有方法:**
|
||||
```python
|
||||
# Schema initialization
|
||||
def init(self) -> None # Replace single table with three tables
|
||||
|
||||
# Insert operations
|
||||
def insert(self, collection, s, p, o) -> None # Write to all three tables
|
||||
|
||||
# Query operations (API unchanged, implementation optimized)
|
||||
def get_all(self, collection, limit=50) # Use triples_by_subject
|
||||
def get_s(self, collection, s, limit=10) # Use triples_by_subject
|
||||
def get_p(self, collection, p, limit=10) # Use triples_by_po
|
||||
def get_o(self, collection, o, limit=10) # Use triples_by_object
|
||||
def get_sp(self, collection, s, p, limit=10) # Use triples_by_subject
|
||||
def get_po(self, collection, p, o, limit=10) # Use triples_by_po (NO ALLOW FILTERING!)
|
||||
def get_os(self, collection, o, s, limit=10) # Use triples_by_subject
|
||||
def get_spo(self, collection, s, p, o, limit=10) # Use triples_by_subject
|
||||
|
||||
# Collection management
|
||||
def delete_collection(self, collection) -> None # Delete from all three tables
|
||||
```
|
||||
|
||||
#### 集成文件 (无需修改任何逻辑)
|
||||
|
||||
**`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`**
|
||||
无需修改 - 使用现有的知识图谱 API
|
||||
自动受益于性能改进
|
||||
|
||||
**`trustgraph-flow/trustgraph/query/triples/cassandra/service.py`**
|
||||
无需修改 - 使用现有的知识图谱 API
|
||||
自动受益于性能改进
|
||||
|
||||
### 需要更新的测试文件
|
||||
|
||||
#### 单元测试
|
||||
**`tests/unit/test_storage/test_triples_cassandra_storage.py`**
|
||||
更新测试预期,以适应模式更改
|
||||
添加多表一致性测试
|
||||
验证查询计划中是否包含 ALLOW FILTERING
|
||||
|
||||
**`tests/unit/test_query/test_triples_cassandra_query.py`**
|
||||
更新性能断言
|
||||
对所有 8 种查询模式进行针对新表的测试
|
||||
验证查询是否路由到正确的表
|
||||
|
||||
#### 集成测试
|
||||
**`tests/integration/test_cassandra_integration.py`**
|
||||
使用新模式进行端到端测试
|
||||
性能基准测试比较
|
||||
跨表的数据一致性验证
|
||||
|
||||
**`tests/unit/test_storage/test_cassandra_config_integration.py`**
|
||||
更新模式验证测试
|
||||
测试迁移场景
|
||||
|
||||
### 实施策略
|
||||
|
||||
#### 第一阶段:模式和核心方法
|
||||
1. **重写 `init()` 方法** - 创建四个表而不是一个
|
||||
2. **重写 `insert()` 方法** - 批量写入所有四个表
|
||||
3. **实现预处理语句** - 以获得最佳性能
|
||||
4. **添加表路由逻辑** - 将查询定向到最佳表
|
||||
5. **实现集合删除** - 从 triples_collection 中读取,批量删除所有表中的数据
|
||||
|
||||
#### 第二阶段:查询方法优化
|
||||
1. **重写每个 get_* 方法** 以使用最佳表
|
||||
2. **删除所有 ALLOW FILTERING 的用法**
|
||||
3. **实现高效的聚类键使用**
|
||||
4. **添加查询性能日志记录**
|
||||
|
||||
#### 第三阶段:集合管理
|
||||
1. **更新 `delete_collection()`** - 从所有三个表中删除
|
||||
2. **添加一致性验证** - 确保所有表保持同步
|
||||
3. **实现批量操作** - 用于原子级多表操作
|
||||
|
||||
### 关键实施细节
|
||||
|
||||
#### 批量写入策略
|
||||
```python
|
||||
def insert(self, collection, s, p, o):
|
||||
batch = BatchStatement()
|
||||
|
||||
# Insert into all four tables
|
||||
batch.add(self.insert_subject_stmt, (collection, s, p, o))
|
||||
batch.add(self.insert_po_stmt, (collection, p, o, s))
|
||||
batch.add(self.insert_object_stmt, (collection, o, s, p))
|
||||
batch.add(self.insert_collection_stmt, (collection, s, p, o))
|
||||
|
||||
self.session.execute(batch)
|
||||
```
|
||||
|
||||
#### 查询路由逻辑
|
||||
```python
|
||||
def get_po(self, collection, p, o, limit=10):
|
||||
# Route to triples_p table - NO ALLOW FILTERING!
|
||||
return self.session.execute(
|
||||
self.get_po_stmt,
|
||||
(collection, p, o, limit)
|
||||
)
|
||||
|
||||
def get_spo(self, collection, s, p, o, limit=10):
|
||||
# Route to triples_collection table for exact SPO lookup
|
||||
return self.session.execute(
|
||||
self.get_spo_stmt,
|
||||
(collection, s, p, o, limit)
|
||||
)
|
||||
```
|
||||
|
||||
#### 集合删除逻辑
|
||||
```python
|
||||
def delete_collection(self, collection):
|
||||
# Step 1: Read all triples from collection table
|
||||
rows = self.session.execute(
|
||||
f"SELECT s, p, o FROM {self.collection_table} WHERE collection = %s",
|
||||
(collection,)
|
||||
)
|
||||
|
||||
# Step 2: Batch delete from all 4 tables
|
||||
batch = BatchStatement()
|
||||
count = 0
|
||||
|
||||
for row in rows:
|
||||
s, p, o = row.s, row.p, row.o
|
||||
|
||||
# Delete using full partition keys for each table
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.subject_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.po_table} WHERE collection = ? AND p = ? AND o = ? AND s = ?"
|
||||
), (collection, p, o, s))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.object_table} WHERE collection = ? AND o = ? AND s = ? AND p = ?"
|
||||
), (collection, o, s, p))
|
||||
|
||||
batch.add(SimpleStatement(
|
||||
f"DELETE FROM {self.collection_table} WHERE collection = ? AND s = ? AND p = ? AND o = ?"
|
||||
), (collection, s, p, o))
|
||||
|
||||
count += 1
|
||||
|
||||
# Execute every 100 triples to avoid oversized batches
|
||||
if count % 100 == 0:
|
||||
self.session.execute(batch)
|
||||
batch = BatchStatement()
|
||||
|
||||
# Execute remaining deletions
|
||||
if count % 100 != 0:
|
||||
self.session.execute(batch)
|
||||
|
||||
logger.info(f"Deleted {count} triples from collection {collection}")
|
||||
```
|
||||
|
||||
#### 预处理语句优化
|
||||
```python
|
||||
def prepare_statements(self):
|
||||
# Cache prepared statements for better performance
|
||||
self.insert_subject_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.subject_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_po_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.po_table} (collection, p, o, s) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_object_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.object_table} (collection, o, s, p) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
self.insert_collection_stmt = self.session.prepare(
|
||||
f"INSERT INTO {self.collection_table} (collection, s, p, o) VALUES (?, ?, ?, ?)"
|
||||
)
|
||||
# ... query statements
|
||||
```
|
||||
|
||||
## 迁移策略
|
||||
|
||||
### 数据迁移方法
|
||||
|
||||
#### 选项 1:蓝绿部署(推荐)
|
||||
1. **并行部署新模式和现有模式** - 暂时使用不同的表名
|
||||
2. **双写期** - 在过渡期间同时写入旧模式和新模式
|
||||
3. **后台迁移** - 将现有数据复制到新表中
|
||||
4. **切换读取** - 在数据迁移完成后,将查询路由到新表中
|
||||
5. **删除旧表** - 在验证期结束后
|
||||
|
||||
#### 选项 2:原地迁移
|
||||
1. **模式添加** - 在现有键空间中创建新表
|
||||
2. **数据迁移脚本** - 批量从旧表复制到新表
|
||||
3. **应用程序更新** - 在迁移完成后部署新代码
|
||||
4. **清理旧表** - 删除旧表和索引
|
||||
|
||||
### 向后兼容性
|
||||
|
||||
#### 部署策略
|
||||
```python
|
||||
# Environment variable to control table usage during migration
|
||||
USE_LEGACY_TABLES = os.getenv('CASSANDRA_USE_LEGACY', 'false').lower() == 'true'
|
||||
|
||||
class KnowledgeGraph:
|
||||
def __init__(self, ...):
|
||||
if USE_LEGACY_TABLES:
|
||||
self.init_legacy_schema()
|
||||
else:
|
||||
self.init_optimized_schema()
|
||||
```
|
||||
|
||||
#### 迁移脚本
|
||||
```python
|
||||
def migrate_data():
|
||||
# Read from old table
|
||||
old_triples = session.execute("SELECT collection, s, p, o FROM triples")
|
||||
|
||||
# Batch write to new tables
|
||||
for batch in batched(old_triples, 100):
|
||||
batch_stmt = BatchStatement()
|
||||
for row in batch:
|
||||
# Add to all three new tables
|
||||
batch_stmt.add(insert_subject_stmt, row)
|
||||
batch_stmt.add(insert_po_stmt, (row.collection, row.p, row.o, row.s))
|
||||
batch_stmt.add(insert_object_stmt, (row.collection, row.o, row.s, row.p))
|
||||
session.execute(batch_stmt)
|
||||
```
|
||||
|
||||
### 验证策略
|
||||
|
||||
#### 数据一致性检查
|
||||
```python
|
||||
def validate_migration():
|
||||
# Count total records in old vs new tables
|
||||
old_count = session.execute("SELECT COUNT(*) FROM triples WHERE collection = ?", (collection,))
|
||||
new_count = session.execute("SELECT COUNT(*) FROM triples_by_subject WHERE collection = ?", (collection,))
|
||||
|
||||
assert old_count == new_count, f"Record count mismatch: {old_count} vs {new_count}"
|
||||
|
||||
# Spot check random samples
|
||||
sample_queries = generate_test_queries()
|
||||
for query in sample_queries:
|
||||
old_result = execute_legacy_query(query)
|
||||
new_result = execute_optimized_query(query)
|
||||
assert old_result == new_result, f"Query results differ for {query}"
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 性能测试
|
||||
|
||||
#### 基准测试场景
|
||||
1. **查询性能比较**
|
||||
所有 8 种查询类型的性能指标(测试前后)
|
||||
重点关注 get_po 性能改进(消除 ALLOW FILTERING)
|
||||
测量不同数据规模下的查询延迟
|
||||
|
||||
2. **负载测试**
|
||||
并发查询执行
|
||||
批量操作的写入吞吐量
|
||||
内存和 CPU 利用率
|
||||
|
||||
3. **可伸缩性测试**
|
||||
随着集合大小增加的性能
|
||||
多集合查询的分布
|
||||
集群节点利用率
|
||||
|
||||
#### 测试数据集
|
||||
**小型:** 每个集合 10K 个三元组
|
||||
**中型:** 每个集合 100K 个三元组
|
||||
**大型:** 1M+ 个三元组
|
||||
**多个集合:** 测试分区分布
|
||||
|
||||
### 功能测试
|
||||
|
||||
#### 单元测试更新
|
||||
```python
|
||||
# Example test structure for new implementation
|
||||
class TestCassandraKGPerformance:
|
||||
def test_get_po_no_allow_filtering(self):
|
||||
# Verify get_po queries don't use ALLOW FILTERING
|
||||
with patch('cassandra.cluster.Session.execute') as mock_execute:
|
||||
kg.get_po('test_collection', 'predicate', 'object')
|
||||
executed_query = mock_execute.call_args[0][0]
|
||||
assert 'ALLOW FILTERING' not in executed_query
|
||||
|
||||
def test_multi_table_consistency(self):
|
||||
# Verify all tables stay in sync
|
||||
kg.insert('test', 's1', 'p1', 'o1')
|
||||
|
||||
# Check all tables contain the triple
|
||||
assert_triple_exists('triples_by_subject', 'test', 's1', 'p1', 'o1')
|
||||
assert_triple_exists('triples_by_po', 'test', 'p1', 'o1', 's1')
|
||||
assert_triple_exists('triples_by_object', 'test', 'o1', 's1', 'p1')
|
||||
```
|
||||
|
||||
#### 集成测试更新
|
||||
```python
|
||||
class TestCassandraIntegration:
|
||||
def test_query_performance_regression(self):
|
||||
# Ensure new implementation is faster than old
|
||||
old_time = benchmark_legacy_get_po()
|
||||
new_time = benchmark_optimized_get_po()
|
||||
assert new_time < old_time * 0.5 # At least 50% improvement
|
||||
|
||||
def test_end_to_end_workflow(self):
|
||||
# Test complete write -> query -> delete cycle
|
||||
# Verify no performance degradation in integration
|
||||
```
|
||||
|
||||
### 回滚计划
|
||||
|
||||
#### 快速回滚策略
|
||||
1. **环境变量切换** - 立即切换回旧版表
|
||||
2. **保留旧版表** - 在性能得到验证之前,不要删除
|
||||
3. **监控警报** - 基于错误率/延迟的自动化回滚触发
|
||||
|
||||
#### 回滚验证
|
||||
```python
|
||||
def rollback_to_legacy():
|
||||
# Set environment variable
|
||||
os.environ['CASSANDRA_USE_LEGACY'] = 'true'
|
||||
|
||||
# Restart services to pick up change
|
||||
restart_cassandra_services()
|
||||
|
||||
# Validate functionality
|
||||
run_smoke_tests()
|
||||
```
|
||||
|
||||
## 风险与考量
|
||||
|
||||
### 性能风险
|
||||
**写入延迟增加** - 每个插入操作需要 4 次写入(比 3 表方案多 33%)
|
||||
**存储开销** - 需要 4 倍的存储空间(比 3 表方案多 33%)
|
||||
**批量写入失败** - 需要适当的错误处理
|
||||
**删除复杂性** - 集合删除需要先读取再删除的循环
|
||||
|
||||
### 运维风险
|
||||
**迁移复杂性** - 大数据集的数据迁移
|
||||
**一致性挑战** - 确保所有表保持同步
|
||||
**监控缺失** - 需要新的指标来监控多表操作
|
||||
|
||||
### 缓解策略
|
||||
1. **逐步推广** - 从小型集合开始
|
||||
2. **全面监控** - 跟踪所有性能指标
|
||||
3. **自动化验证** - 持续进行一致性检查
|
||||
4. **快速回滚能力** - 基于环境选择表
|
||||
|
||||
## 成功标准
|
||||
|
||||
### 性能改进
|
||||
[ ] **消除 ALLOW FILTERING** - `get_po` 和 `get_os` 查询在没有过滤的情况下运行
|
||||
[ ] **查询延迟降低** - 查询响应时间提高 50% 以上
|
||||
[ ] **更好的负载分布** - 没有热分区,集群节点上的负载分布均匀
|
||||
[ ] **可扩展的性能** - 查询时间与结果大小成正比,而不是与总数据量成正比
|
||||
|
||||
### 功能需求
|
||||
[ ] **API 兼容性** - 所有现有代码继续保持不变
|
||||
[ ] **数据一致性** - 所有三个表保持同步
|
||||
[ ] **零数据丢失** - 迁移保留所有现有三元组
|
||||
[ ] **向后兼容性** - 能够回滚到旧模式
|
||||
|
||||
### 运维需求
|
||||
[ ] **安全迁移** - 蓝绿部署,具有回滚能力
|
||||
[ ] **监控覆盖** - 针对多表操作的全面指标
|
||||
[ ] **测试覆盖** - 所有查询模式都经过性能基准测试
|
||||
[ ] **文档** - 更新部署和运维流程
|
||||
|
||||
## 时间线
|
||||
|
||||
### 第一阶段:实施
|
||||
[ ] 使用多表模式重写 `cassandra_kg.py`
|
||||
[ ] 实施批量写入操作
|
||||
[ ] 添加准备语句优化
|
||||
[ ] 更新单元测试
|
||||
|
||||
### 第二阶段:集成测试
|
||||
[ ] 更新集成测试
|
||||
[ ] 性能基准测试
|
||||
[ ] 使用真实数据量的负载测试
|
||||
[ ] 数据一致性验证脚本
|
||||
|
||||
### 第三阶段:迁移规划
|
||||
[ ] 蓝绿部署脚本
|
||||
[ ] 数据迁移工具
|
||||
[ ] 监控仪表板更新
|
||||
[ ] 回滚流程
|
||||
|
||||
### 第四阶段:生产部署
|
||||
[ ] 逐步推广到生产环境
|
||||
[ ] 性能监控和验证
|
||||
[ ] 清理旧表
|
||||
[ ] 文档更新
|
||||
|
||||
## 结论
|
||||
|
||||
这种多表反规范化策略直接解决了两个关键的性能瓶颈:
|
||||
|
||||
1. **消除昂贵的 ALLOW FILTERING**,通过为每种查询模式提供最佳的表结构
|
||||
2. **提高聚类效率**,通过复合分区键来合理地分配负载
|
||||
|
||||
该方法利用了 Cassandra 的优势,同时保持完整的 API 兼容性,确保现有代码能够自动受益于性能改进。
|
||||
410
docs/tech-specs/collection-management.ar.md
Normal file
410
docs/tech-specs/collection-management.ar.md
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
---
|
||||
layout: default
|
||||
title: "مواصفات فنية لإدارة المجموعات"
|
||||
parent: "Arabic (Beta)"
|
||||
---
|
||||
|
||||
# مواصفات فنية لإدارة المجموعات
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
تصف هذه المواصفات إمكانات إدارة المجموعات لـ TrustGraph، والتي تتطلب إنشاء مجموعات بشكل صريح وتوفر تحكمًا مباشرًا في دورة حياة المجموعة. يجب إنشاء المجموعات بشكل صريح قبل استخدامها، مما يضمن المزامنة الصحيحة بين بيانات وصفية أمين المكتبة وجميع الواجهات الخلفية للتخزين. تدعم هذه الميزة أربع حالات استخدام رئيسية:
|
||||
|
||||
1. **إنشاء المجموعة**: إنشاء مجموعات بشكل صريح قبل تخزين البيانات
|
||||
2. **قائمة المجموعات**: عرض جميع المجموعات الموجودة في النظام
|
||||
3. **إدارة بيانات وصفية المجموعة**: تحديث أسماء المجموعات والأوصاف والعلامات
|
||||
4. **حذف المجموعة**: إزالة المجموعات والبيانات المرتبطة بها عبر جميع أنواع التخزين
|
||||
|
||||
## الأهداف
|
||||
|
||||
**إنشاء المجموعة بشكل صريح**: تتطلب أن يتم إنشاء المجموعات قبل تخزين البيانات
|
||||
**مزامنة التخزين**: ضمان وجود المجموعات في جميع الواجهات الخلفية للتخزين (المتجهات، والكائنات، والثلاثيات)
|
||||
**إمكانية رؤية المجموعة**: تمكين المستخدمين من سرد وفحص جميع المجموعات في بيئتهم
|
||||
**تنظيف المجموعة**: السماح بحذف المجموعات التي لم تعد مطلوبة
|
||||
**تنظيم المجموعة**: دعم العلامات والملصقات لتتبع واكتشاف المجموعة بشكل أفضل
|
||||
**إدارة البيانات الوصفية**: ربط بيانات وصفية ذات مغزى بالمجموعات من أجل الوضوح التشغيلي
|
||||
**اكتشاف المجموعة**: تسهيل العثور على مجموعات معينة من خلال التصفية والبحث
|
||||
**الشفافية التشغيلية**: توفير رؤية واضحة لدورة حياة المجموعة واستخدامها
|
||||
**إدارة الموارد**: تمكين تنظيف المجموعات غير المستخدمة لتحسين استخدام الموارد
|
||||
**سلامة البيانات**: منع وجود مجموعات معزولة في التخزين بدون تتبع البيانات الوصفية
|
||||
|
||||
## الخلفية
|
||||
|
||||
في السابق، كانت المجموعات في TrustGraph يتم إنشاؤها ضمنيًا أثناء عمليات تحميل البيانات، مما أدى إلى مشاكل في المزامنة حيث يمكن أن توجد المجموعات في الواجهات الخلفية للتخزين بدون بيانات وصفية مقابلة في أمين المكتبة. وقد أدى ذلك إلى تحديات إدارية وإمكانية وجود بيانات معزولة.
|
||||
|
||||
يعالج نموذج إنشاء المجموعة الصريح هذه المشكلات عن طريق:
|
||||
طلب إنشاء المجموعات قبل استخدامها عبر `tg-set-collection`
|
||||
بث إنشاء المجموعة إلى جميع الواجهات الخلفية للتخزين
|
||||
الحفاظ على حالة متزامنة بين بيانات وصفية أمين المكتبة والتخزين
|
||||
منع الكتابة إلى المجموعات غير الموجودة
|
||||
توفير إدارة واضحة لدورة حياة المجموعة
|
||||
|
||||
تحدد هذه المواصفات نموذج إدارة المجموعة الصريح. من خلال طلب إنشاء المجموعة بشكل صريح، تضمن TrustGraph:
|
||||
تتبع المجموعات في بيانات وصفية أمين المكتبة من لحظة إنشائها
|
||||
أن تكون جميع الواجهات الخلفية للتخزين على علم بالمجموعات قبل استقبال البيانات
|
||||
عدم وجود مجموعات معزولة في التخزين
|
||||
رؤية وتحكم واضحين في دورة حياة المجموعة
|
||||
معالجة أخطاء متسقة عند الإشارة العمليات إلى مجموعات غير موجودة
|
||||
|
||||
## التصميم الفني
|
||||
|
||||
### البنية التحتية
|
||||
|
||||
سيتم تنفيذ نظام إدارة المجموعة داخل البنية التحتية الحالية لـ TrustGraph:
|
||||
|
||||
1. **تكامل خدمة أمين المكتبة**
|
||||
سيتم إضافة عمليات إدارة المجموعة إلى خدمة أمين المكتبة الحالية
|
||||
لا توجد خدمة جديدة مطلوبة - تستفيد من أنماط المصادقة والوصول الحالية
|
||||
تتعامل مع قائمة المجموعات وحذفها وإدارة بياناتها الوصفية
|
||||
|
||||
الوحدة: trustgraph-librarian
|
||||
|
||||
2. **جدول بيانات وصفية المجموعة في Cassandra**
|
||||
جدول جديد في مساحة مفاتيح أمين المكتبة الحالية
|
||||
يخزن بيانات وصفية المجموعة مع وصول المستخدم
|
||||
المفتاح الأساسي: (user_id, collection_id) لضمان تعدد المستأجرين المناسب
|
||||
|
||||
الوحدة: trustgraph-librarian
|
||||
|
||||
3. **واجهة سطر الأوامر لإدارة المجموعة**
|
||||
واجهة سطر أوامر لعمليات المجموعة
|
||||
يوفر أوامر للقائمة والحذف والملصقات والعلامات
|
||||
يتكامل مع إطار عمل سطر الأوامر الحالي
|
||||
|
||||
الوحدة: trustgraph-cli
|
||||
|
||||
### نماذج البيانات
|
||||
|
||||
#### جدول بيانات وصفية المجموعة في Cassandra
|
||||
|
||||
سيتم تخزين بيانات وصفية المجموعة في جدول Cassandra منظم في مساحة مفاتيح أمين المكتبة:
|
||||
|
||||
```sql
|
||||
CREATE TABLE collections (
|
||||
user text,
|
||||
collection text,
|
||||
name text,
|
||||
description text,
|
||||
tags set<text>,
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
PRIMARY KEY (user, collection)
|
||||
);
|
||||
```
|
||||
|
||||
هيكل الجدول:
|
||||
**user**: + **collection**: مفتاح أساسي مركب يضمن عزل المستخدم
|
||||
**name**: اسم المجموعة الذي يمكن قراءته بواسطة الإنسان
|
||||
**description**: وصف تفصيلي لغرض المجموعة
|
||||
**tags**: مجموعة من العلامات لتصنيف وتصفية
|
||||
**created_at**: طابع زمني لإنشاء المجموعة
|
||||
**updated_at**: طابع زمني لآخر تعديل
|
||||
|
||||
هذا النهج يسمح بـ:
|
||||
إدارة مجموعات متعددة المستأجرين مع عزل المستخدم
|
||||
استعلام فعال حسب المستخدم والمجموعة
|
||||
نظام تصنيف مرن للتنظيم
|
||||
تتبع دورة حياة المجموعة للحصول على رؤى تشغيلية
|
||||
|
||||
#### دورة حياة المجموعة
|
||||
|
||||
يتم إنشاء المجموعات بشكل صريح في المكتبة قبل أن تتمكن عمليات البيانات من المضي قدمًا:
|
||||
|
||||
1. **إنشاء المجموعة** (مساران):
|
||||
|
||||
**المسار أ: الإنشاء الذي يبدأه المستخدم** عبر `tg-set-collection`:
|
||||
يقوم المستخدم بتوفير معرف المجموعة والاسم والوصف والعلامات
|
||||
تقوم المكتبة بإنشاء سجل بيانات وصفية في جدول `collections`
|
||||
تقوم المكتبة ببث "إنشاء مجموعة" إلى جميع الواجهات الخلفية للتخزين
|
||||
تقوم جميع معالجات التخزين بإنشاء المجموعة وتأكيد النجاح
|
||||
أصبحت المجموعة الآن جاهزة لعمليات البيانات
|
||||
|
||||
**المسار ب: الإنشاء التلقائي عند إرسال المستند**:
|
||||
يقوم المستخدم بإرسال مستند يحدد معرف مجموعة
|
||||
تتحقق المكتبة مما إذا كانت المجموعة موجودة في جدول البيانات الوصفية
|
||||
إذا لم تكن موجودة: تقوم المكتبة بإنشاء بيانات وصفية مع القيم الافتراضية (الاسم = معرف المجموعة، وصف/علامات فارغة)
|
||||
تقوم المكتبة ببث "إنشاء مجموعة" إلى جميع الواجهات الخلفية للتخزين
|
||||
تقوم جميع معالجات التخزين بإنشاء المجموعة وتأكيد النجاح
|
||||
تستمر معالجة المستند مع إنشاء المجموعة الآن
|
||||
|
||||
يضمن كلا المسارين وجود المجموعة في بيانات المكتبة الوصفية وجميع الواجهات الخلفية للتخزين قبل السماح بعمليات البيانات.
|
||||
|
||||
2. **التحقق من التخزين**: تتحقق عمليات الكتابة من وجود المجموعة:
|
||||
تتحقق معالجات التخزين من حالة المجموعة قبل قبول عمليات الكتابة
|
||||
تؤدي عمليات الكتابة إلى مجموعات غير موجودة إلى إرجاع خطأ
|
||||
يمنع هذا عمليات الكتابة المباشرة التي تتجاوز منطق إنشاء المجموعة الخاص بالمكتبة
|
||||
|
||||
3. **سلوك الاستعلام**: تتعامل عمليات الاستعلام مع المجموعات غير الموجودة بأمان:
|
||||
تؤدي الاستعلامات إلى مجموعات غير موجودة إلى إرجاع نتائج فارغة
|
||||
لا يتم إرجاع أي خطأ لعمليات الاستعلام
|
||||
يسمح بالاستكشاف دون الحاجة إلى وجود المجموعة
|
||||
|
||||
4. **تحديثات البيانات الوصفية**: يمكن للمستخدمين تحديث بيانات وصفية للمجموعة بعد الإنشاء:
|
||||
قم بتحديث الاسم والوصف والعلامات عبر `tg-set-collection`
|
||||
تنطبق التحديثات على بيانات المكتبة الوصفية فقط
|
||||
تحتفظ الواجهات الخلفية للتخزين بالمجموعة ولكن لا يتم نشر تحديثات البيانات الوصفية
|
||||
|
||||
5. **الحذف الصريح**: يقوم المستخدمون بحذف المجموعات عبر `tg-delete-collection`:
|
||||
تقوم المكتبة ببث "حذف مجموعة" إلى جميع الواجهات الخلفية للتخزين
|
||||
تنتظر تأكيدًا من جميع معالجات التخزين
|
||||
تحذف سجل بيانات المكتبة الوصفية فقط بعد اكتمال تنظيف التخزين
|
||||
يضمن عدم وجود بيانات متبقية في التخزين
|
||||
|
||||
**المبدأ الأساسي**: المكتبة هي نقطة التحكم الوحيدة لإنشاء المجموعة. سواء تم بدءها بأمر المستخدم أو بإرسال مستند، تضمن المكتبة تتبع البيانات الوصفية المناسبة ومزامنة الواجهة الخلفية للتخزين قبل السماح بعمليات البيانات.
|
||||
|
||||
العمليات المطلوبة:
|
||||
**إنشاء مجموعة**: عملية المستخدم عبر `tg-set-collection` أو تلقائيًا عند إرسال مستند
|
||||
**تحديث بيانات وصفية للمجموعة**: عملية المستخدم لتعديل الاسم والوصف والعلامات
|
||||
**حذف مجموعة**: عملية المستخدم لإزالة المجموعة والبيانات المرتبطة بها عبر جميع المتاجر
|
||||
**قائمة المجموعات**: عملية المستخدم لعرض المجموعات مع التصفية حسب العلامات
|
||||
|
||||
#### إدارة المجموعة عبر المتاجر
|
||||
|
||||
توجد المجموعات عبر واجهات خلفية تخزين متعددة في TrustGraph:
|
||||
**مخازن المتجهات** (Qdrant، Milvus، Pinecone): تخزن التضمينات والبيانات المتجهة
|
||||
**مخازن الكائنات** (Cassandra): تخزن المستندات وبيانات الملف
|
||||
**مخازن الثلاثيات** (Cassandra، Neo4j، Memgraph، FalkorDB): تخزن بيانات الرسم البياني/RDF
|
||||
|
||||
Each store type implements:
|
||||
**Collection State Tracking**: Maintain knowledge of which collections exist
|
||||
**Collection Creation**: Accept and process "create-collection" operations
|
||||
**Collection Validation**: Check collection exists before accepting writes
|
||||
**Collection Deletion**: Remove all data for specified collection
|
||||
|
||||
The librarian service coordinates collection operations across all store types, ensuring:
|
||||
Collections created in all backends before use
|
||||
All backends confirm creation before returning success
|
||||
Synchronized collection lifecycle across storage types
|
||||
Consistent error handling when collections don't exist
|
||||
|
||||
#### Collection State Tracking by Storage Type
|
||||
|
||||
Each storage backend tracks collection state differently based on its capabilities:
|
||||
|
||||
**Cassandra Triple Store:**
|
||||
Uses existing `triples_collection` table
|
||||
Creates system marker triple when collection created
|
||||
Query: `SELECT collection FROM triples_collection WHERE collection = ? LIMIT 1`
|
||||
Efficient single-partition check for collection existence
|
||||
|
||||
**Qdrant/Milvus/Pinecone Vector Stores:**
|
||||
Native collection APIs provide existence checking
|
||||
Collections created with proper vector configuration
|
||||
`collection_exists()` method uses storage API
|
||||
Collection creation validates dimension requirements
|
||||
|
||||
**Neo4j/Memgraph/FalkorDB Graph Stores:**
|
||||
Use `:CollectionMetadata` nodes to track collections
|
||||
Node properties: `{user, collection, created_at}`
|
||||
Query: `MATCH (c:CollectionMetadata {user: $user, collection: $collection})`
|
||||
Separate from data nodes for clean separation
|
||||
Enables efficient collection listing and validation
|
||||
|
||||
**Cassandra Object Store:**
|
||||
Uses collection metadata table or marker rows
|
||||
Similar pattern to triple store
|
||||
Validates collection before document writes
|
||||
|
||||
### APIs
|
||||
|
||||
Collection Management APIs (Librarian):
|
||||
**Create/Update Collection**: Create new collection or update existing metadata via `tg-set-collection`
|
||||
**List Collections**: Retrieve collections for a user with optional tag filtering
|
||||
**Delete Collection**: Remove collection and associated data, cascading to all store types
|
||||
|
||||
Storage Management APIs (All Storage Processors):
|
||||
**Create Collection**: Handle "create-collection" operation, establish collection in storage
|
||||
**Delete Collection**: Handle "delete-collection" operation, remove all collection data
|
||||
**Collection Exists Check**: Internal validation before accepting write operations
|
||||
|
||||
Data Operation APIs (Modified Behavior):
|
||||
**Write APIs**: Validate collection exists before accepting data, return error if not
|
||||
**Query APIs**: Return empty results for non-existent collections without error
|
||||
|
||||
### Implementation Details
|
||||
|
||||
The implementation will follow existing TrustGraph patterns for service integration and CLI command structure.
|
||||
|
||||
#### Collection Deletion Cascade
|
||||
|
||||
When a user initiates collection deletion through the librarian service:
|
||||
|
||||
1. **Metadata Validation**: Verify collection exists and user has permission to delete
|
||||
2. **Store Cascade**: Librarian coordinates deletion across all store writers:
|
||||
Vector store writer: Remove embeddings and vector indexes for the user and collection
|
||||
Object store writer: Remove documents and files for the user and collection
|
||||
Triple store writer: Remove graph data and triples for the user and collection
|
||||
3. **Metadata Cleanup**: Remove collection metadata record from Cassandra
|
||||
4. **Error Handling**: If any store deletion fails, maintain consistency through rollback or retry mechanisms
|
||||
|
||||
#### Collection Management Interface
|
||||
|
||||
**⚠️ LEGACY APPROACH - REPLACED BY CONFIG-BASED PATTERN**
|
||||
|
||||
The queue-based architecture described below has been replaced with a config-based approach using `CollectionConfigHandler`. All storage backends now receive collection updates via config push messages instead of dedicated management queues.
|
||||
|
||||
~~All store writers implement a standardized collection management interface with a common schema:~~
|
||||
|
||||
~~**Message Schema (`StorageManagementRequest`):**~~
|
||||
```json
|
||||
{
|
||||
"operation": "create-collection" | "delete-collection",
|
||||
"user": "user123",
|
||||
"collection": "documents-2024"
|
||||
}
|
||||
```
|
||||
|
||||
~~**هيكلة قائمة الانتظار:**~~
|
||||
~~**قائمة انتظار إدارة مخزن المتجهات** (`vector-storage-management`): مخازن المتجهات/التضمينات~~
|
||||
~~**قائمة انتظار إدارة مخزن الكائنات** (`object-storage-management`): مخازن الكائنات/المستندات~~
|
||||
~~**قائمة انتظار إدارة مخزن الثلاثيات** (`triples-storage-management`): مخازن الرسم البياني/RDF~~
|
||||
~~**قائمة انتظار استجابة التخزين** (`storage-management-response`): يتم إرسال جميع الاستجابات هنا~~
|
||||
|
||||
**التنفيذ الحالي:**
|
||||
|
||||
تستخدم جميع واجهات التخزين الخلفية الآن `CollectionConfigHandler`:
|
||||
**تكامل دفع التكوين**: تسجل خدمات التخزين للحصول على إشعارات دفع التكوين
|
||||
**المزامنة التلقائية**: يتم إنشاء/حذف المجموعات بناءً على تغييرات التكوين
|
||||
**نموذج تصريحي**: يتم تعريف المجموعات في خدمة التكوين، وتقوم الواجهات الخلفية بالمزامنة للمطابقة
|
||||
**لا يوجد طلب/استجابة**: يلغي تكامل التنسيق وتتبع الاستجابة
|
||||
**تتبع حالة المجموعة**: يتم الحفاظ عليه عبر ذاكرة التخزين المؤقت `known_collections`
|
||||
**عمليات قابلة للعكس**: من الآمن معالجة نفس التكوين عدة مرات
|
||||
|
||||
تقوم كل واجهة تخزين خلفية بتنفيذ:
|
||||
`create_collection(user: str, collection: str, metadata: dict)` - إنشاء هياكل المجموعة
|
||||
`delete_collection(user: str, collection: str)` - إزالة جميع بيانات المجموعة
|
||||
`collection_exists(user: str, collection: str) -> bool` - التحقق من الصحة قبل الكتابة
|
||||
|
||||
#### إعادة هيكلة مخزن الثلاثيات Cassandra
|
||||
|
||||
كجزء من هذا التنفيذ، سيتم إعادة هيكلة مخزن الثلاثيات Cassandra من نموذج جدول لكل مجموعة إلى نموذج جدول موحد:
|
||||
|
||||
**الهيكلة الحالية:**
|
||||
مساحة مفاتيح لكل مستخدم، وجدول منفصل لكل مجموعة
|
||||
المخطط: `(s, p, o)` مع `PRIMARY KEY (s, p, o)`
|
||||
أسماء الجداول: تصبح مجموعات المستخدمين جداول Cassandra منفصلة
|
||||
|
||||
**الهيكلة الجديدة:**
|
||||
مساحة مفاتيح لكل مستخدم، وجدول "ثلاثيات" واحد لجميع المجموعات
|
||||
المخطط: `(collection, s, p, o)` مع `PRIMARY KEY (collection, s, p, o)`
|
||||
عزل المجموعة من خلال تقسيم المجموعة
|
||||
|
||||
**التغييرات المطلوبة:**
|
||||
|
||||
1. **إعادة هيكلة فئة TrustGraph** (`trustgraph/direct/cassandra.py`):
|
||||
إزالة المعلمة `table` من المُنشئ، واستخدام جدول "ثلاثيات" ثابت
|
||||
إضافة المعلمة `collection` إلى جميع الطرق
|
||||
تحديث المخطط لتضمين المجموعة كأول عمود
|
||||
**تحديثات الفهرس**: سيتم إنشاء فهارس جديدة لدعم جميع أنماط الاستعلام الثمانية:
|
||||
فهرس على `(s)` للاستعلامات المستندة إلى الموضوع
|
||||
فهرس على `(p)` للاستعلامات المستندة إلى الرابط
|
||||
فهرس على `(o)` للاستعلامات المستندة إلى الكائن
|
||||
ملاحظة: لا تدعم Cassandra فهارس ثانوية متعددة الأعمدة، لذا هذه هي فهارس أحادية العمود
|
||||
|
||||
**أداء نمط الاستعلام:**
|
||||
✅ `get_all()` - فحص التقسيم على `collection`
|
||||
✅ `get_s(s)` - يستخدم المفتاح الأساسي بكفاءة (`collection, s`)
|
||||
✅ `get_p(p)` - يستخدم `idx_p` مع تصفية `collection`
|
||||
✅ `get_o(o)` - يستخدم `idx_o` مع تصفية `collection`
|
||||
✅ `get_sp(s, p)` - يستخدم المفتاح الأساسي بكفاءة (`collection, s, p`)
|
||||
⚠️ `get_po(p, o)` - يتطلب `ALLOW FILTERING` (يستخدم إما `idx_p` أو `idx_o` بالإضافة إلى التصفية)
|
||||
✅ `get_os(o, s)` - يستخدم `idx_o` مع تصفية إضافية على `s`
|
||||
✅ `get_spo(s, p, o)` - يستخدم المفتاح الأساسي بكفاءة
|
||||
|
||||
**ملاحظة حول ALLOW FILTERING**: يتطلب نمط استعلام `get_po` `ALLOW FILTERING` لأنه يحتاج إلى كل من قيود الرابط والكائن بدون فهرس مركب مناسب. هذا مقبول لأن نمط الاستعلام هذا أقل شيوعًا من الاستعلامات المستندة إلى الموضوع في الاستخدام النموذجي لمخزن الثلاثيات.
|
||||
|
||||
2. **تحديثات كاتب التخزين** (`trustgraph/storage/triples/cassandra/write.py`):
|
||||
الحفاظ على اتصال TrustGraph واحد لكل مستخدم بدلاً من لكل (مستخدم، مجموعة)
|
||||
تمرير المجموعة إلى عمليات الإدراج
|
||||
تحسين استخدام الموارد مع عدد أقل من الاتصالات
|
||||
|
||||
3. **تحديثات خدمة الاستعلام** (`trustgraph/query/triples/cassandra/service.py`):
|
||||
اتصال TrustGraph واحد لكل مستخدم
|
||||
تمرير المجموعة إلى جميع عمليات الاستعلام
|
||||
الحفاظ على نفس منطق الاستعلام مع معلمة المجموعة
|
||||
|
||||
**الفوائد:**
|
||||
**تبسيط حذف المجموعة**: حذف باستخدام مفتاح التقسيم `collection` عبر جميع الجداول الأربعة
|
||||
**كفاءة الموارد**: عدد أقل من اتصالات قاعدة البيانات وكائنات الجدول
|
||||
**العمليات عبر المجموعات**: من الأسهل تنفيذ العمليات التي تمتد عبر مجموعات متعددة
|
||||
**هيكلة متسقة**: تتماشى مع نهج بيانات التعريف الموحد للمجموعة
|
||||
**التحقق من صحة المجموعة**: من السهل التحقق من وجود المجموعة عبر جدول `triples_collection`
|
||||
|
||||
ستكون عمليات المجموعة ذرية قدر الإمكان، وستوفر معالجة أخطاء والتحقق المناسبين.
|
||||
|
||||
## اعتبارات الأمان
|
||||
|
||||
تتطلب عمليات إدارة المجموعة تفويضًا مناسبًا لمنع الوصول غير المصرح به أو حذف المجموعات. سيتم مواءمة التحكم في الوصول مع نماذج الأمان الحالية لـ TrustGraph.
|
||||
|
||||
## اعتبارات الأداء
|
||||
|
||||
قد تتطلب عمليات سرد المجموعة الترقيم في البيئات التي تحتوي على عدد كبير من المجموعات. يجب تحسين استعلامات البيانات الوصفية للأنماط الشائعة للتصفية.
|
||||
|
||||
## استراتيجية الاختبار
|
||||
|
||||
ستغطي الاختبارات الشاملة ما يلي:
|
||||
سير عمل إنشاء المجموعة من البداية إلى النهاية
|
||||
مزامنة الواجهة الخلفية للتخزين
|
||||
التحقق من صحة الكتابة للمجموعات غير الموجودة
|
||||
معالجة الاستعلامات للمجموعات غير الموجودة
|
||||
حذف المجموعة بالتتالي عبر جميع المستودعات
|
||||
معالجة الأخطاء وسيناريوهات الاسترداد
|
||||
اختبارات الوحدة لكل واجهة خلفية للتخزين
|
||||
اختبارات التكامل للعمليات عبر المستودعات
|
||||
|
||||
## حالة التنفيذ
|
||||
|
||||
### ✅ المكونات المكتملة
|
||||
|
||||
1. **خدمة إدارة المجموعة Librarian** (`trustgraph-flow/trustgraph/librarian/collection_manager.py`)
|
||||
عمليات CRUD للبيانات الوصفية للمجموعة (القائمة، التحديث، الحذف)
|
||||
تكامل جدول بيانات وصفية للمجموعة في Cassandra عبر `LibraryTableStore`
|
||||
تنسيق حذف المجموعة بالتتالي عبر جميع أنواع التخزين
|
||||
معالجة الطلبات/الاستجابات غير المتزامنة مع إدارة الأخطاء المناسبة
|
||||
|
||||
2. **مخطط البيانات الوصفية للمجموعة** (`trustgraph-base/trustgraph/schema/services/collection.py`)
|
||||
مخططات `CollectionManagementRequest` و `CollectionManagementResponse`
|
||||
مخطط `CollectionMetadata` لسجلات المجموعة
|
||||
تعريفات موضوع قائمة انتظار الطلبات/الاستجابات للمجموعة
|
||||
|
||||
3. **مخطط إدارة التخزين** (`trustgraph-base/trustgraph/schema/services/storage.py`)
|
||||
مخططات `StorageManagementRequest` و `StorageManagementResponse`
|
||||
تم تعريف مواضيع قائمة انتظار إدارة التخزين
|
||||
تنسيق الرسائل لعمليات المجموعة على مستوى التخزين
|
||||
|
||||
4. **مخطط Cassandra المكون من 4 جداول** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py`)
|
||||
مفاتيح تقسيم مركبة لأداء الاستعلام
|
||||
جدول `triples_collection` لاستعلامات SPO وتتبع الحذف
|
||||
تم تنفيذ حذف المجموعة بنمط القراءة ثم الحذف
|
||||
|
||||
### ✅ الترحيل إلى النمط المستند إلى التكوين - مكتمل
|
||||
|
||||
**تم ترحيل جميع الواجهات الخلفية للتخزين من نمط قائمة الانتظار إلى النمط المستند إلى التكوين `CollectionConfigHandler`.**
|
||||
|
||||
عمليات الترحيل المكتملة:
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/neo4j/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/memgraph/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/falkordb/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
|
||||
جميع الواجهات الخلفية الآن:
|
||||
ترث من `CollectionConfigHandler`
|
||||
تسجيل للحصول على إشعارات دفع التكوين عبر `self.register_config_handler(self.on_collection_config)`
|
||||
تنفيذ `create_collection(user, collection, metadata)` و `delete_collection(user, collection)`
|
||||
استخدام `collection_exists(user, collection)` للتحقق قبل الكتابة
|
||||
المزامنة التلقائية مع تغييرات خدمة التكوين
|
||||
|
||||
تم إزالة البنية التحتية لقائمة الانتظار القديمة:
|
||||
✅ تمت إزالة مخططات `StorageManagementRequest` و `StorageManagementResponse`
|
||||
✅ تمت إزالة تعريفات موضوع قائمة انتظار إدارة التخزين
|
||||
✅ تمت إزالة المستهلك/المنتج لإدارة التخزين من جميع الواجهات الخلفية
|
||||
✅ تمت إزالة معالجات `on_storage_management` من جميع الواجهات الخلفية
|
||||
410
docs/tech-specs/collection-management.es.md
Normal file
410
docs/tech-specs/collection-management.es.md
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificación Técnica de Gestión de Colecciones"
|
||||
parent: "Spanish (Beta)"
|
||||
---
|
||||
|
||||
# Especificación Técnica de Gestión de Colecciones
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Descripción General
|
||||
|
||||
Esta especificación describe las capacidades de gestión de colecciones para TrustGraph, que requieren la creación explícita de colecciones y proporcionan un control directo sobre el ciclo de vida de la colección. Las colecciones deben crearse explícitamente antes de su uso, lo que garantiza una sincronización adecuada entre los metadatos del bibliotecario y todos los backends de almacenamiento. La función admite cuatro casos de uso principales:
|
||||
|
||||
1. **Creación de Colecciones**: Crear explícitamente colecciones antes de almacenar datos
|
||||
2. **Listado de Colecciones**: Ver todas las colecciones existentes en el sistema
|
||||
3. **Gestión de Metadatos de Colecciones**: Actualizar los nombres, las descripciones y las etiquetas de las colecciones
|
||||
4. **Eliminación de Colecciones**: Eliminar colecciones y sus datos asociados en todos los tipos de almacenamiento
|
||||
|
||||
## Objetivos
|
||||
|
||||
**Creación Explícita de Colecciones**: Requerir que las colecciones se creen antes de que se puedan almacenar datos
|
||||
**Sincronización de Almacenamiento**: Asegurar que las colecciones existan en todos los backends de almacenamiento (vectores, objetos, triples)
|
||||
**Visibilidad de Colecciones**: Permitir a los usuarios listar e inspeccionar todas las colecciones en su entorno
|
||||
**Limpieza de Colecciones**: Permitir la eliminación de colecciones que ya no son necesarias
|
||||
**Organización de Colecciones**: Compatibilidad con etiquetas para un mejor seguimiento y descubrimiento de colecciones
|
||||
**Gestión de Metadatos**: Asociar metadatos significativos con las colecciones para una mayor claridad operativa
|
||||
**Descubrimiento de Colecciones**: Facilitar la búsqueda de colecciones específicas mediante el filtrado y la búsqueda
|
||||
**Transparencia Operacional**: Proporcionar una visibilidad clara del ciclo de vida y el uso de las colecciones
|
||||
**Gestión de Recursos**: Permitir la limpieza de colecciones no utilizadas para optimizar la utilización de recursos
|
||||
**Integridad de Datos**: Prevenir la existencia de colecciones huérfanas en el almacenamiento sin seguimiento de metadatos
|
||||
|
||||
## Antecedentes
|
||||
|
||||
Anteriormente, las colecciones en TrustGraph se creaban implícitamente durante las operaciones de carga de datos, lo que provocaba problemas de sincronización en los que las colecciones podían existir en los backends de almacenamiento sin metadatos correspondientes en el bibliotecario. Esto creaba desafíos de gestión y posibles datos huérfanos.
|
||||
|
||||
El modelo de creación explícita de colecciones aborda estos problemas mediante:
|
||||
La necesidad de crear colecciones antes de su uso a través de `tg-set-collection`
|
||||
La difusión de la creación de colecciones a todos los backends de almacenamiento
|
||||
El mantenimiento de un estado sincronizado entre los metadatos del bibliotecario y el almacenamiento
|
||||
La prevención de escrituras en colecciones inexistentes
|
||||
La provisión de una gestión clara del ciclo de vida de las colecciones
|
||||
|
||||
Esta especificación define el modelo de gestión explícita de colecciones. Al requerir la creación explícita de colecciones, TrustGraph garantiza:
|
||||
Que las colecciones se rastreen en los metadatos del bibliotecario desde su creación
|
||||
Que todos los backends de almacenamiento conozcan las colecciones antes de recibir datos
|
||||
Que no existan colecciones huérfanas en el almacenamiento
|
||||
Una visibilidad y un control claros del ciclo de vida de las colecciones
|
||||
Un manejo de errores coherente cuando las operaciones hacen referencia a colecciones inexistentes
|
||||
|
||||
## Diseño Técnico
|
||||
|
||||
### Arquitectura
|
||||
|
||||
El sistema de gestión de colecciones se implementará dentro de la infraestructura existente de TrustGraph:
|
||||
|
||||
1. **Integración del Servicio del Bibliotecario**
|
||||
Las operaciones de gestión de colecciones se agregarán al servicio del bibliotecario existente
|
||||
No se requiere un nuevo servicio; aprovecha los patrones de autenticación y acceso existentes
|
||||
Gestiona el listado, la eliminación y la gestión de metadatos de colecciones
|
||||
|
||||
Módulo: trustgraph-librarian
|
||||
|
||||
2. **Tabla de Metadatos de Colecciones de Cassandra**
|
||||
Nueva tabla en el keyspace existente del bibliotecario
|
||||
Almacena metadatos de colecciones con acceso específico al usuario
|
||||
Clave primaria: (user_id, collection_id) para una correcta multi-tenencia
|
||||
|
||||
Módulo: trustgraph-librarian
|
||||
|
||||
3. **CLI de Gestión de Colecciones**
|
||||
Interfaz de línea de comandos para operaciones de colecciones
|
||||
Proporciona comandos de listado, eliminación, etiquetado y gestión de etiquetas
|
||||
Se integra con el marco de CLI existente
|
||||
|
||||
Módulo: trustgraph-cli
|
||||
|
||||
### Modelos de Datos
|
||||
|
||||
#### Tabla de Metadatos de Colecciones de Cassandra
|
||||
|
||||
Los metadatos de la colección se almacenarán en una tabla estructurada de Cassandra en el keyspace del bibliotecario:
|
||||
|
||||
```sql
|
||||
CREATE TABLE collections (
|
||||
user text,
|
||||
collection text,
|
||||
name text,
|
||||
description text,
|
||||
tags set<text>,
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
PRIMARY KEY (user, collection)
|
||||
);
|
||||
```
|
||||
|
||||
Estructura de la tabla:
|
||||
**user** + **collection**: Clave primaria compuesta que asegura el aislamiento del usuario
|
||||
**name**: Nombre legible por humanos de la colección
|
||||
**description**: Descripción detallada del propósito de la colección
|
||||
**tags**: Conjunto de etiquetas para la categorización y el filtrado
|
||||
**created_at**: Marca de tiempo de creación de la colección
|
||||
**updated_at**: Marca de tiempo de la última modificación
|
||||
|
||||
Este enfoque permite:
|
||||
Gestión de colecciones multi-inquilino con aislamiento de usuario
|
||||
Consulta eficiente por usuario y colección
|
||||
Sistema de etiquetado flexible para la organización
|
||||
Seguimiento del ciclo de vida para obtener información operativa
|
||||
|
||||
#### Ciclo de vida de la colección
|
||||
|
||||
Las colecciones se crean explícitamente en el bibliotecario antes de que puedan comenzar las operaciones de datos:
|
||||
|
||||
1. **Creación de la colección** (Dos caminos):
|
||||
|
||||
**Camino A: Creación iniciada por el usuario** a través de `tg-set-collection`:
|
||||
El usuario proporciona el ID de la colección, el nombre, la descripción y las etiquetas
|
||||
El bibliotecario crea un registro de metadatos en la tabla `collections`
|
||||
El bibliotecario transmite "crear-colección" a todos los backends de almacenamiento
|
||||
Todos los procesadores de almacenamiento crean la colección y confirman el éxito
|
||||
La colección está ahora lista para las operaciones de datos
|
||||
|
||||
**Camino B: Creación automática al enviar un documento**:
|
||||
El usuario envía un documento que especifica un ID de colección
|
||||
El bibliotecario comprueba si existe la colección en la tabla de metadatos
|
||||
Si no existe: El bibliotecario crea metadatos con valores predeterminados (nombre=id_colección, descripción/etiquetas vacías)
|
||||
El bibliotecario transmite "crear-colección" a todos los backends de almacenamiento
|
||||
Todos los procesadores de almacenamiento crean la colección y confirman el éxito
|
||||
El procesamiento del documento continúa con la colección ahora establecida
|
||||
|
||||
Ambos caminos garantizan que la colección exista en los metadatos del bibliotecario Y en todos los backends de almacenamiento antes de permitir las operaciones de datos.
|
||||
|
||||
2. **Validación de almacenamiento**: Las operaciones de escritura validan la existencia de la colección:
|
||||
Los procesadores de almacenamiento comprueban el estado de la colección antes de aceptar escrituras
|
||||
Las escrituras en colecciones inexistentes devuelven un error
|
||||
Esto evita las escrituras directas que omiten la lógica de creación de colecciones del bibliotecario
|
||||
|
||||
3. **Comportamiento de la consulta**: Las operaciones de consulta gestionan las colecciones inexistentes de forma elegante:
|
||||
Las consultas a colecciones inexistentes devuelven resultados vacíos
|
||||
No se lanza ningún error para las operaciones de consulta
|
||||
Permite la exploración sin requerir que la colección exista
|
||||
|
||||
4. **Actualizaciones de metadatos**: Los usuarios pueden actualizar los metadatos de la colección después de la creación:
|
||||
Actualice el nombre, la descripción y las etiquetas a través de `tg-set-collection`
|
||||
Las actualizaciones se aplican solo a los metadatos del bibliotecario
|
||||
Los backends de almacenamiento mantienen la colección, pero las actualizaciones de metadatos no se propagan
|
||||
|
||||
5. **Eliminación explícita**: Los usuarios eliminan las colecciones a través de `tg-delete-collection`:
|
||||
El bibliotecario transmite "eliminar-colección" a todos los backends de almacenamiento
|
||||
Espera la confirmación de todos los procesadores de almacenamiento
|
||||
Elimina el registro de metadatos del bibliotecario solo después de que se complete la limpieza del almacenamiento
|
||||
Garantiza que no queden datos huérfanos en el almacenamiento
|
||||
|
||||
**Principio clave**: El bibliotecario es el único punto de control para la creación de colecciones. Ya sea iniciado por un comando de usuario o por la presentación de un documento, el bibliotecario garantiza el seguimiento adecuado de los metadatos y la sincronización del backend de almacenamiento antes de permitir las operaciones de datos.
|
||||
|
||||
Operaciones requeridas:
|
||||
**Crear colección**: Operación del usuario a través de `tg-set-collection` O automática al enviar un documento
|
||||
**Actualizar metadatos de la colección**: Operación del usuario para modificar el nombre, la descripción y las etiquetas
|
||||
**Eliminar colección**: Operación del usuario para eliminar la colección y sus datos en todos los almacenes
|
||||
**Listar colecciones**: Operación del usuario para ver las colecciones con filtrado por etiquetas
|
||||
|
||||
#### Gestión de colecciones multi-almacén
|
||||
|
||||
Las colecciones existen en varios backends de almacenamiento en TrustGraph:
|
||||
**Tiendas vectoriales** (Qdrant, Milvus, Pinecone): Almacena incrustaciones y datos vectoriales
|
||||
**Tiendas de objetos** (Cassandra): Almacena documentos y datos de archivos
|
||||
**Tiendas de triples** (Cassandra, Neo4j, Memgraph, FalkorDB): Almacena datos de grafos/RDF
|
||||
Después de la última línea traducida, incluir una línea final que contenga exactamente: [[__END_OF_TRANSLATION__]]
|
||||
Cada tipo de tienda implementa:
|
||||
**Seguimiento del estado de la colección**: Mantener conocimiento de qué colecciones existen
|
||||
**Creación de colecciones**: Aceptar y procesar operaciones de "crear-colección"
|
||||
**Validación de colecciones**: Comprobar si la colección existe antes de aceptar escrituras
|
||||
**Eliminación de colecciones**: Eliminar todos los datos para la colección especificada
|
||||
|
||||
El servicio de bibliotecario coordina las operaciones de colección en todos los tipos de tienda, asegurando:
|
||||
Que las colecciones se creen en todos los backends antes de su uso
|
||||
Que todos los backends confirmen la creación antes de devolver el éxito
|
||||
Un ciclo de vida de colección sincronizado en todos los tipos de almacenamiento
|
||||
Un manejo de errores consistente cuando las colecciones no existen
|
||||
|
||||
#### Seguimiento del estado de la colección por tipo de almacenamiento
|
||||
|
||||
Cada backend de almacenamiento realiza el seguimiento del estado de la colección de manera diferente según sus capacidades:
|
||||
|
||||
**Triple Store de Cassandra:**
|
||||
Utiliza la tabla `triples_collection` existente
|
||||
Crea un triple de marcador de sistema cuando se crea una colección
|
||||
Consulta: `SELECT collection FROM triples_collection WHERE collection = ? LIMIT 1`
|
||||
Comprobación de existencia de colección eficiente de partición única
|
||||
|
||||
**Almacenes de vectores Qdrant/Milvus/Pinecone:**
|
||||
Las API nativas de colección proporcionan la comprobación de existencia
|
||||
Las colecciones se crean con la configuración de vectores adecuada
|
||||
El método `collection_exists()` utiliza la API de almacenamiento
|
||||
La creación de colecciones valida los requisitos de dimensión
|
||||
|
||||
**Almacenes de grafos Neo4j/Memgraph/FalkorDB:**
|
||||
Utiliza nodos `:CollectionMetadata` para realizar el seguimiento de las colecciones
|
||||
Propiedades del nodo: `{user, collection, created_at}`
|
||||
Consulta: `MATCH (c:CollectionMetadata {user: $user, collection: $collection})`
|
||||
Separado de los nodos de datos para una separación limpia
|
||||
Permite una enumeración y validación eficientes de las colecciones
|
||||
|
||||
**Almacén de objetos de Cassandra:**
|
||||
Utiliza la tabla de metadatos de la colección o filas de marcador
|
||||
Patrón similar al triple store
|
||||
Valida la colección antes de las escrituras de documentos
|
||||
|
||||
### API
|
||||
|
||||
API de administración de colecciones (Bibliotecario):
|
||||
**Crear/Actualizar colección**: Crear una nueva colección o actualizar los metadatos existentes a través de `tg-set-collection`
|
||||
**Listar colecciones**: Recuperar colecciones para un usuario con filtrado opcional por etiqueta
|
||||
**Eliminar colección**: Eliminar la colección y los datos asociados, propagándose a todos los tipos de tienda
|
||||
|
||||
API de administración de almacenamiento (Todos los procesadores de almacenamiento):
|
||||
**Crear colección**: Manejar la operación de "crear-colección", establecer la colección en el almacenamiento
|
||||
**Eliminar colección**: Manejar la operación de "eliminar-colección", eliminar todos los datos de la colección
|
||||
**Comprobación de existencia de colección**: Validación interna antes de aceptar operaciones de escritura
|
||||
|
||||
API de operación de datos (Comportamiento modificado):
|
||||
**API de escritura**: Validar que la colección exista antes de aceptar datos, devolver un error si no es así
|
||||
**API de consulta**: Devolver resultados vacíos para colecciones inexistentes sin error
|
||||
|
||||
### Detalles de implementación
|
||||
|
||||
La implementación seguirá los patrones existentes de TrustGraph para la integración de servicios y la estructura de comandos de la CLI.
|
||||
|
||||
#### Eliminación en cascada de colecciones
|
||||
|
||||
Cuando un usuario inicia la eliminación de una colección a través del servicio de bibliotecario:
|
||||
|
||||
1. **Validación de metadatos**: Verificar que la colección exista y que el usuario tenga permiso para eliminarla
|
||||
2. **Propagación a tiendas**: El bibliotecario coordina la eliminación en todos los escritores de tiendas:
|
||||
Escritor de almacenamiento de vectores: Eliminar incrustaciones e índices de vectores para el usuario y la colección
|
||||
Escritor de almacenamiento de objetos: Eliminar documentos y archivos para el usuario y la colección
|
||||
Escritor de triple store: Eliminar datos de grafos y triples para el usuario y la colección
|
||||
3. **Limpieza de metadatos**: Eliminar el registro de metadatos de la colección de Cassandra
|
||||
4. **Manejo de errores**: Si falla la eliminación de alguna tienda, mantener la coherencia a través de mecanismos de reversión o reintento
|
||||
|
||||
#### Interfaz de administración de colecciones
|
||||
|
||||
**⚠️ ENFOQUE ANTIGUO: REEMPLAZADO POR UN PATRÓN BASADO EN CONFIGURACIÓN**
|
||||
|
||||
La arquitectura basada en colas descrita a continuación ha sido reemplazada por un enfoque basado en configuración que utiliza `CollectionConfigHandler`. Todos los backends de almacenamiento ahora reciben actualizaciones de colecciones a través de mensajes de configuración en lugar de colas de administración dedicadas.
|
||||
|
||||
~~Todos los escritores de tiendas implementan una interfaz de administración de colecciones estandarizada con un esquema común:~~
|
||||
|
||||
~~**Esquema de mensaje (`StorageManagementRequest`):**~~
|
||||
```json
|
||||
{
|
||||
"operation": "create-collection" | "delete-collection",
|
||||
"user": "user123",
|
||||
"collection": "documents-2024"
|
||||
}
|
||||
```
|
||||
|
||||
~~**Arquitectura de la Cola:**~~
|
||||
~~**Cola de Gestión de Almacenes Vectoriales** (`vector-storage-management`): Almacenes de vectores/incrustaciones~~
|
||||
~~**Cola de Gestión de Almacenes de Objetos** (`object-storage-management`): Almacenes de objetos/documentos~~
|
||||
~~**Cola de Gestión de Almacenes Triples** (`triples-storage-management`): Almacenes de grafos/RDF~~
|
||||
~~**Cola de Respuestas de Almacenamiento** (`storage-management-response`): Todas las respuestas se envían aquí~~
|
||||
|
||||
**Implementación Actual:**
|
||||
|
||||
Todos los backends de almacenamiento ahora utilizan `CollectionConfigHandler`:
|
||||
**Integración de Configuración Push**: Los servicios de almacenamiento se registran para recibir notificaciones de configuración push.
|
||||
**Sincronización Automática**: Las colecciones se crean/eliminan en función de los cambios de configuración.
|
||||
**Modelo Declarativo**: Las colecciones se definen en el servicio de configuración, y los backends se sincronizan para que coincidan.
|
||||
**Sin Solicitud/Respuesta**: Elimina la sobrecarga de coordinación y el seguimiento de respuestas.
|
||||
**Seguimiento del Estado de la Colección**: Se mantiene a través de la caché `known_collections`.
|
||||
**Operaciones Idempotentes**: Es seguro procesar la misma configuración varias veces.
|
||||
|
||||
Cada backend de almacenamiento implementa:
|
||||
`create_collection(user: str, collection: str, metadata: dict)` - Crear estructuras de colección
|
||||
`delete_collection(user: str, collection: str)` - Eliminar todos los datos de la colección
|
||||
`collection_exists(user: str, collection: str) -> bool` - Validar antes de escribir
|
||||
|
||||
#### Refactorización del Almacén Triples de Cassandra
|
||||
|
||||
Como parte de esta implementación, el almacén triples de Cassandra se refactorizará de un modelo de una tabla por colección a un modelo de una tabla unificada:
|
||||
|
||||
**Arquitectura Actual:**
|
||||
Keyspace por usuario, tabla separada por colección
|
||||
Esquema: `(s, p, o)` con `PRIMARY KEY (s, p, o)`
|
||||
Nombres de tabla: las colecciones de usuario se convierten en tablas separadas de Cassandra.
|
||||
|
||||
**Nueva Arquitectura:**
|
||||
Keyspace por usuario, una sola tabla "triples" para todas las colecciones
|
||||
Esquema: `(collection, s, p, o)` con `PRIMARY KEY (collection, s, p, o)`
|
||||
Aislamiento de colecciones a través de la partición de colecciones
|
||||
|
||||
**Cambios Requeridos:**
|
||||
|
||||
1. **Refactorización de la Clase TrustGraph** (`trustgraph/direct/cassandra.py`):
|
||||
Eliminar el parámetro `table` del constructor, usar la tabla "triples" fija.
|
||||
Agregar el parámetro `collection` a todos los métodos.
|
||||
Actualizar el esquema para incluir la colección como la primera columna.
|
||||
**Actualizaciones de Índice**: Se crearán nuevos índices para admitir los 8 patrones de consulta:
|
||||
Índice en `(s)` para consultas basadas en el sujeto.
|
||||
Índice en `(p)` para consultas basadas en el predicado.
|
||||
Índice en `(o)` para consultas basadas en el objeto.
|
||||
Nota: Cassandra no admite índices secundarios de varias columnas, por lo que estos son índices de una sola columna.
|
||||
|
||||
**Rendimiento del Patrón de Consulta:**
|
||||
✅ `get_all()` - escaneo de partición en `collection`
|
||||
✅ `get_s(s)` - utiliza la clave primaria de manera eficiente (`collection, s`)
|
||||
✅ `get_p(p)` - utiliza `idx_p` con `collection` de filtrado
|
||||
✅ `get_o(o)` - utiliza `idx_o` con `collection` de filtrado
|
||||
✅ `get_sp(s, p)` - utiliza la clave primaria de manera eficiente (`collection, s, p`)
|
||||
⚠️ `get_po(p, o)` - requiere `ALLOW FILTERING` (utiliza `idx_p` o `idx_o` más filtrado)
|
||||
✅ `get_os(o, s)` - utiliza `idx_o` con filtrado adicional en `s`
|
||||
✅ `get_spo(s, p, o)` - utiliza toda la clave primaria de manera eficiente
|
||||
|
||||
**Nota sobre ALLOW FILTERING**: El patrón de consulta `get_po` requiere `ALLOW FILTERING` porque necesita tanto las restricciones de predicado como las de objeto sin un índice compuesto adecuado. Esto es aceptable porque este patrón de consulta es menos común que las consultas basadas en el sujeto en el uso típico de un almacén triples.
|
||||
|
||||
2. **Actualizaciones del Escritor de Almacenamiento** (`trustgraph/storage/triples/cassandra/write.py`):
|
||||
Mantener una única conexión TrustGraph por usuario en lugar de por (usuario, colección).
|
||||
Pasar la colección a las operaciones de inserción.
|
||||
Mejor utilización de recursos con menos conexiones.
|
||||
|
||||
3. **Actualizaciones del Servicio de Consulta** (`trustgraph/query/triples/cassandra/service.py`):
|
||||
Una única conexión TrustGraph por usuario.
|
||||
Pasar la colección a todas las operaciones de consulta.
|
||||
Mantener la misma lógica de consulta con el parámetro de colección.
|
||||
|
||||
**Beneficios:**
|
||||
**Eliminación Simplificada de Colecciones**: Eliminar utilizando la clave de partición `collection` en las 4 tablas.
|
||||
**Eficiencia de Recursos**: Menos conexiones de base de datos y objetos de tabla.
|
||||
**Operaciones entre Colecciones**: Más fácil de implementar operaciones que abarcan múltiples colecciones.
|
||||
**Arquitectura Consistente**: Se alinea con el enfoque unificado de metadatos de colección.
|
||||
**Validación de Colecciones**: Es fácil comprobar la existencia de la colección mediante la tabla `triples_collection`.
|
||||
|
||||
Las operaciones de colección serán atómicas siempre que sea posible y proporcionarán un manejo de errores y una validación adecuados.
|
||||
|
||||
## Consideraciones de seguridad
|
||||
|
||||
Las operaciones de administración de colecciones requieren la autorización adecuada para evitar el acceso no autorizado o la eliminación de colecciones. El control de acceso se alineará con los modelos de seguridad de TrustGraph existentes.
|
||||
|
||||
## Consideraciones de rendimiento
|
||||
|
||||
Las operaciones de listado de colecciones pueden requerir paginación para entornos con un gran número de colecciones. Las consultas de metadatos deben optimizarse para patrones de filtrado comunes.
|
||||
|
||||
## Estrategia de pruebas
|
||||
|
||||
La prueba exhaustiva cubrirá:
|
||||
Flujo de trabajo de creación de colecciones de extremo a extremo
|
||||
Sincronización del almacenamiento en segundo plano
|
||||
Validación de escritura para colecciones inexistentes
|
||||
Manejo de consultas de colecciones inexistentes
|
||||
Eliminación de colecciones en cascada en todos los almacenes
|
||||
Manejo de errores y escenarios de recuperación
|
||||
Pruebas unitarias para cada almacenamiento en segundo plano
|
||||
Pruebas de integración para operaciones entre almacenes
|
||||
|
||||
## Estado de la implementación
|
||||
|
||||
### ✅ Componentes completados
|
||||
|
||||
1. **Servicio de administración de colecciones Librarian** (`trustgraph-flow/trustgraph/librarian/collection_manager.py`)
|
||||
Operaciones CRUD de metadatos de colecciones (listar, actualizar, eliminar)
|
||||
Integración de la tabla de metadatos de colecciones de Cassandra a través de `LibraryTableStore`
|
||||
Coordinación de la eliminación de colecciones en cascada en todos los tipos de almacenamiento
|
||||
Manejo de solicitudes/respuestas asíncronas con una gestión de errores adecuada
|
||||
|
||||
2. **Esquema de metadatos de colecciones** (`trustgraph-base/trustgraph/schema/services/collection.py`)
|
||||
Esquemas `CollectionManagementRequest` y `CollectionManagementResponse`
|
||||
Esquema `CollectionMetadata` para registros de colecciones
|
||||
Definiciones de temas de cola de solicitudes/respuestas de colecciones
|
||||
|
||||
3. **Esquema de administración de almacenamiento** (`trustgraph-base/trustgraph/schema/services/storage.py`)
|
||||
Esquemas `StorageManagementRequest` y `StorageManagementResponse`
|
||||
Temas de cola de administración de almacenamiento definidos
|
||||
Formato de mensaje para operaciones de colecciones a nivel de almacenamiento
|
||||
|
||||
4. **Esquema de tabla Cassandra de 4 tablas** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py`)
|
||||
Claves de partición compuestas para el rendimiento de la consulta
|
||||
Tabla `triples_collection` para consultas SPO y seguimiento de eliminación
|
||||
Implementación de la eliminación de colecciones con el patrón de lectura y eliminación
|
||||
|
||||
### ✅ Migración a patrón basado en configuración - COMPLETADO
|
||||
|
||||
**Todos los backends de almacenamiento se han migrado del patrón basado en cola al patrón `CollectionConfigHandler` basado en configuración.**
|
||||
|
||||
Migraciones completadas:
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/neo4j/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/memgraph/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/falkordb/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
|
||||
Todos los backends ahora:
|
||||
Heredan de `CollectionConfigHandler`
|
||||
Se registran para notificaciones de configuración push a través de `self.register_config_handler(self.on_collection_config)`
|
||||
Implementan `create_collection(user, collection, metadata)` y `delete_collection(user, collection)`
|
||||
Utilizan `collection_exists(user, collection)` para validar antes de escribir
|
||||
Se sincronizan automáticamente con los cambios del servicio de configuración
|
||||
|
||||
Infraestructura basada en cola heredada eliminada:
|
||||
✅ Esquemas `StorageManagementRequest` y `StorageManagementResponse` eliminados
|
||||
✅ Definiciones de temas de cola de administración de almacenamiento eliminadas
|
||||
✅ Consumidor/productor de administración de almacenamiento eliminado de todos los backends
|
||||
✅ Manejadores `on_storage_management` eliminados de todos los backends
|
||||
410
docs/tech-specs/collection-management.he.md
Normal file
410
docs/tech-specs/collection-management.he.md
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
---
|
||||
layout: default
|
||||
title: "מפרט טכני לניהול אוספים"
|
||||
parent: "Hebrew (Beta)"
|
||||
---
|
||||
|
||||
# מפרט טכני לניהול אוספים
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## סקירה כללית
|
||||
|
||||
מפרט זה מתאר את יכולות ניהול האוספים עבור TrustGraph, הדורש יצירת אוספים באופן מפורש ומספק שליטה ישירה על מחזור החיים של האוסף. יש ליצור אוספים באופן מפורש לפני השימוש, כדי להבטיח סנכרון תקין בין מטא-הנתונים של הספרן לבין כל אחסני הנתונים. הפיצ'ר תומך בארבעה תרחישי שימוש עיקריים:
|
||||
|
||||
1. **יצירת אוסף**: ליצור אוספים באופן מפורש לפני אחסון נתונים
|
||||
2. **רשימת אוספים**: להציג את כל האוספים הקיימים במערכת
|
||||
3. **ניהול מטא-נתונים של אוסף**: לעדכן שמות, תיאורים ותגיות של אוספים
|
||||
4. **מחיקת אוסף**: להסיר אוספים ונתונים הקשורים אליהם בכל סוגי האחסון
|
||||
|
||||
## מטרות
|
||||
|
||||
**יצירת אוסף מפורשת**: לדרוש יצירת אוספים לפני שאפשר לאחסן נתונים
|
||||
**סנכרון אחסון**: להבטיח שאוספים קיימים בכל אחסני הנתונים (וקטורים, אובייקטים, טריפלטים)
|
||||
**נראות של אוסף**: לאפשר למשתמשים לרשום ולבדוק את כל האוספים בסביבה שלהם
|
||||
**ניקוי אוספים**: לאפשר מחיקת אוספים שכבר אינם נחוצים
|
||||
**ארגון אוספים**: לתמוך בתגיות ובתוויות למעקב וגילוי טובים יותר של אוספים
|
||||
**ניהול מטא-נתונים**: לקשר מטא-נתונים בעלי משמעות לאוספים לצורך בהירות תפעולית
|
||||
**גילוי אוספים**: להקל על מציאת אוספים ספציפיים באמצעות סינון וחיפוש
|
||||
**שקיפות תפעולית**: לספק נראות ברורה על מחזור החיים ושימוש האוספים
|
||||
**ניהול משאבים**: לאפשר ניקוי של אוספים לא בשימוש כדי לייעל את ניצול המשאבים
|
||||
**שלמות נתונים**: למנוע קיום של אוספים יתומים באחסון ללא מעקב מטא-נתונים
|
||||
|
||||
## רקע
|
||||
|
||||
בעבר, אוספים ב-TrustGraph נוצרו באופן סמוי במהלך פעולות טעינת נתונים, מה שגרם לבעיות סנכרון שבהן אוספים יכלו להתקיים באחסני נתונים ללא מטא-נתונים תואמים בספרן. זה יצר אתגרים בניהול ואפשרות של נתונים יתומים.
|
||||
|
||||
מודל יצירת האוספים המפורש פותר בעיות אלה על ידי:
|
||||
דרישה ליצירת אוספים לפני השימוש באמצעות `tg-set-collection`
|
||||
שידור יצירת אוסף לכל אחסני הנתונים
|
||||
שמירה על מצב מסונכרן בין מטא-נתונים של הספרן ואחסון
|
||||
מניעת כתיבה לאוספים שאינם קיימים
|
||||
מתן ניהול ברור של מחזור החיים של האוסף
|
||||
|
||||
מפרט זה מגדיר את מודל ניהול האוספים המפורש. על ידי דרישה ליצירת אוסף מפורשת, TrustGraph מבטיחה:
|
||||
אוספים מתועדים במטא-נתונים של הספרן החל מיצירתם
|
||||
כל אחסני הנתונים מודעים לאוספים לפני קבלת נתונים
|
||||
לא קיימים אוספים יתומים באחסון
|
||||
נראות ושליטה ברורים על מחזור החיים של האוסף
|
||||
טיפול שגיאות עקבי כאשר פעולות מפנות לאוספים שאינם קיימים
|
||||
|
||||
## עיצוב טכני
|
||||
|
||||
### ארכיטקטורה
|
||||
|
||||
מערכת ניהול האוספים תיושם בתוך התשתית הקיימת של TrustGraph:
|
||||
|
||||
1. **שילוב עם שירות הספרן**
|
||||
פעולות ניהול אוספים יתווספו לשירות הספרן הקיים
|
||||
לא נדרש שירות חדש - משתמש בדפוסי אימות וגישה קיימים
|
||||
מטפל ברשימת אוספים, מחיקה וניהול מטא-נתונים
|
||||
|
||||
מודול: trustgraph-librarian
|
||||
|
||||
2. **טבלת מטא-נתונים של אוסף ב-Cassandra**
|
||||
טבלה חדשה במרחב המפתחות הקיים של הספרן
|
||||
מאחסנת מטא-נתונים של אוסף עם גישה מבוססת משתמש
|
||||
מפתח ראשי: (user_id, collection_id) עבור ריבוי שוכרים תקין
|
||||
|
||||
מודול: trustgraph-librarian
|
||||
|
||||
3. **ממשק שורת פקודה לניהול אוספים**
|
||||
ממשק שורת פקודה לפעולות ניהול אוספים
|
||||
מספק פקודות לרשימה, מחיקה, תווית וניהול תגיות
|
||||
משתלב עם מסגרת שורת הפקודה הקיימת
|
||||
|
||||
מודול: trustgraph-cli
|
||||
|
||||
### מודלים של נתונים
|
||||
|
||||
#### טבלת מטא-נתונים של אוסף ב-Cassandra
|
||||
|
||||
מטא-הנתונים של האוסף יאוחסנו בטבלה מובנית ב-Cassandra במרחב המפתחות של הספרן:
|
||||
|
||||
```sql
|
||||
CREATE TABLE collections (
|
||||
user text,
|
||||
collection text,
|
||||
name text,
|
||||
description text,
|
||||
tags set<text>,
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
PRIMARY KEY (user, collection)
|
||||
);
|
||||
```
|
||||
|
||||
מבנה טבלה:
|
||||
**user** + **collection**: מפתח ראשי מורכב המבטיח בידוד משתמשים
|
||||
**name**: שם קריא לבן-אדם של האוסף
|
||||
**description**: תיאור מפורט של מטרת האוסף
|
||||
**tags**: קבוצת תגיות למיון וסינון
|
||||
**created_at**: חותמת זמן של יצירת האוסף
|
||||
**updated_at**: חותמת זמן של השינוי האחרון
|
||||
|
||||
גישה זו מאפשרת:
|
||||
ניהול אוספים מרובי-דיירים עם בידוד משתמשים
|
||||
שאילתות יעילות לפי משתמש ואוסף
|
||||
מערכת תיוג גמישה לארגון
|
||||
מעקב אחר מחזור החיים לצורך תובנות תפעוליות
|
||||
|
||||
#### מחזור החיים של אוסף
|
||||
|
||||
אוספים נוצרים באופן מפורש בספרן לפני שניתן לבצע פעולות נתונים:
|
||||
|
||||
1. **יצירת אוסף** (שני מסלולים):
|
||||
|
||||
**מסלול א': יצירה על ידי משתמש** באמצעות `tg-set-collection`:
|
||||
המשתמש מספק מזהה אוסף, שם, תיאור ותגיות
|
||||
הספרן יוצר רשומת מטא-נתונים בטבלת `collections`
|
||||
הספרן משדר "create-collection" לכל מערכות האחסון
|
||||
כל מעבדי האחסון יוצרים את האוסף ומאשרים הצלחה
|
||||
האוסף מוכן כעת לפעולות נתונים
|
||||
|
||||
**מסלול ב': יצירה אוטומטית בעת הגשת מסמך**:
|
||||
המשתמש מגיש מסמך המציין מזהה אוסף
|
||||
הספרן בודק אם האוסף קיים בטבלת המטא-נתונים
|
||||
אם לא קיים: הספרן יוצר מטא-נתונים עם ברירות מחדל (שם=מזהה האוסף, תיאור/תגיות ריקים)
|
||||
הספרן משדר "create-collection" לכל מערכות האחסון
|
||||
כל מעבדי האחסון יוצרים את האוסף ומאשרים הצלחה
|
||||
עיבוד המסמך ממשיך עם יצירת האוסף
|
||||
|
||||
שני המסלולים מבטיחים שהאוסף קיים במטא-נתונים של הספרן ובכל מערכות האחסון לפני ביצוע פעולות נתונים.
|
||||
|
||||
2. **אימות אחסון**: פעולות כתיבה מאמתות את קיומו של האוסף:
|
||||
מעבדי האחסון בודקים את מצב האוסף לפני קבלת כתיבות
|
||||
כתיבות לאוספים שאינם קיימים מחזירות שגיאה
|
||||
זה מונע כתיבות ישירות העוקפות את לוגיקת יצירת האוסף של הספרן
|
||||
|
||||
3. **התנהגות שאילתה**: פעולות שאילתה מטפלות באוספים שאינם קיימים בצורה חלקה:
|
||||
שאילתות לאוספים שאינם קיימים מחזירות תוצאות ריקות
|
||||
לא נזרקת שגיאה עבור פעולות שאילתה
|
||||
מאפשרת חקירה מבלי לדרוש קיום האוסף
|
||||
|
||||
4. **עדכוני מטא-נתונים**: משתמשים יכולים לעדכן מטא-נתונים של אוסף לאחר יצירתו:
|
||||
עדכון שם, תיאור ותגיות באמצעות `tg-set-collection`
|
||||
העדכונים חלים רק על מטא-נתונים של הספרן
|
||||
מערכות האחסון שומרות על האוסף, אך עדכוני מטא-נתונים אינם מועברים
|
||||
|
||||
5. **מחיקה מפורשת**: משתמשים מוחקים אוספים באמצעות `tg-delete-collection`:
|
||||
הספרן משדר "delete-collection" לכל מערכות האחסון
|
||||
ממתין לאישור מכל מעבדי האחסון
|
||||
מוחק רשומת מטא-נתונים של הספרן רק לאחר השלמת הניקוי של האחסון
|
||||
מבטיח שלא יישארו נתונים יתומים באחסון
|
||||
|
||||
**עקרון מפתח**: הספרן הוא נקודת השליטה היחידה ליצירת אוספים. בין אם זהו פקודה של משתמש או הגשת מסמך, הספרן מבטיח מעקב נכון אחר מטא-נתונים וסנכרון של מערכות אחסון לפני שהוא מאפשר פעולות נתונים.
|
||||
|
||||
פעולות נדרשות:
|
||||
**יצירת אוסף**: פעולה של משתמש באמצעות `tg-set-collection` או אוטומטית בעת הגשת מסמך
|
||||
**עדכון מטא-נתונים של אוסף**: פעולה של משתמש לשינוי שם, תיאור ותגיות
|
||||
**מחיקת אוסף**: פעולה של משתמש להסרת אוסף ונתונים שלו בכל האחסונים
|
||||
**רשימת אוספים**: פעולה של משתמש לצפייה באוספים עם סינון לפי תגיות
|
||||
|
||||
#### ניהול אוספים מרובי-חנות
|
||||
|
||||
אוספים קיימים על פני מספר מערכות אחסון ב-TrustGraph:
|
||||
**מאגרי וקטורים** (Qdrant, Milvus, Pinecone): אחסון הטבעות ונתוני וקטור
|
||||
**מאגרי אובייקטים** (Cassandra): אחסון מסמכים ונתוני קבצים
|
||||
**מאגרי משולשים** (Cassandra, Neo4j, Memgraph, FalkorDB): אחסון נתוני גרף/RDF
|
||||
פלט חוזה (יש לעקוב בדיוק אחר הפורמט הבא).
|
||||
כל סוג חנות מיישם:
|
||||
**מעקב אחר מצב איסוף**: שמירה על ידע אילו איסופים קיימים
|
||||
**יצירת איסוף**: קבלת עיבוד פעולות "יצירת-איסוף"
|
||||
**אימות איסוף**: בדיקת קיום האיסוף לפני קבלת כתיבות
|
||||
**מחיקת איסוף**: הסרת כל הנתונים עבור איסוף מסוים
|
||||
|
||||
שירות הספרין מתאם פעולות איסוף בין כל סוגי החנויות, תוך הבטחה ש:
|
||||
איסופים נוצרים בכל ה-backends לפני השימוש
|
||||
כל ה-backends מאשרים יצירה לפני החזרת הצלחה
|
||||
מחזור חיים מסונכרן של איסופים בין סוגי אחסון
|
||||
טיפול עקבי בשגיאות כאשר איסופים אינם קיימים
|
||||
|
||||
#### מעקב אחר מצב איסוף לפי סוג אחסון
|
||||
|
||||
כל backend אחסון עוקב אחר מצב איסוף בצורה שונה בהתאם ליכולותיו:
|
||||
|
||||
**Cassandra Triple Store:**
|
||||
משתמש בטבלה קיימת `triples_collection`
|
||||
יוצר טריפל מערכת כאשר איסוף נוצר
|
||||
שאילתה: `SELECT collection FROM triples_collection WHERE collection = ? LIMIT 1`
|
||||
בדיקה יעילה של מחיצה יחידה לקיום איסוף
|
||||
|
||||
**Qdrant/Milvus/Pinecone Vector Stores:**
|
||||
ממשקי API מקוריים לאיסופים מספקים בדיקת קיום
|
||||
איסופים נוצרים עם תצורת וקטור מתאימה
|
||||
שיטה `collection_exists()` משתמשת ב-API של האחסון
|
||||
יצירת איסוף מאמת דרישות מימד
|
||||
|
||||
**Neo4j/Memgraph/FalkorDB Graph Stores:**
|
||||
משתמש בצמתים `:CollectionMetadata` כדי לעקוב אחר איסופים
|
||||
מאפייני צומת: `{user, collection, created_at}`
|
||||
שאילתה: `MATCH (c:CollectionMetadata {user: $user, collection: $collection})`
|
||||
נפרד מצמתי נתונים לצורך הפרדה נקייה
|
||||
מאפשר רישום ואימות יעילים של איסופים
|
||||
|
||||
**Cassandra Object Store:**
|
||||
משתמש בטבלת מטא-נתונים של איסוף או שורות סימון
|
||||
דפוס דומה ל-triple store
|
||||
מאמת איסוף לפני כתיבת מסמכים
|
||||
|
||||
### ממשקים
|
||||
|
||||
ממשקי ניהול איסופים (ספרין):
|
||||
**יצירת/עדכון איסוף**: יצירת איסוף חדש או עדכון מטא-נתונים קיימים באמצעות `tg-set-collection`
|
||||
**רשימת איסופים**: שליפה של איסופים עבור משתמש עם סינון תגיות אופציונלי
|
||||
**מחיקת איסוף**: הסרת איסוף ונתונים קשורים, עם העברה לכל סוגי החנויות
|
||||
|
||||
ממשקי ניהול אחסון (כל מעבדי אחסון):
|
||||
**יצירת איסוף**: טיפול בפעולת "יצירת-איסוף", הקמת איסוף באחסון
|
||||
**מחיקת איסוף**: טיפול בפעולת "מחיקת-איסוף", הסרת כל נתוני איסוף
|
||||
**בדיקת קיום איסוף**: אימות פנימי לפני קבלת פעולות כתיבה
|
||||
|
||||
ממשקי פעולות נתונים (התנהגות משתנה):
|
||||
**ממשקי כתיבה**: אימות קיום איסוף לפני קבלת נתונים, החזרת שגיאה אם לא קיים
|
||||
**ממשקי שאילתה**: החזרת תוצאות ריקות עבור איסופים שאינם קיימים ללא שגיאה
|
||||
|
||||
### פרטי יישום
|
||||
|
||||
היישום יעקוב לדפוסי TrustGraph קיימים לשילוב שירותים ומבנה פקודות שורת פקודה.
|
||||
|
||||
#### מחיקת איסוף בשרשרת
|
||||
|
||||
כאשר משתמש יוזם מחיקת איסוף דרך שירות הספרין:
|
||||
|
||||
1. **אימות מטא-נתונים**: אימות קיום איסוף ושהמשתמש מורשה למחוק
|
||||
2. **שרשרת אחסון**: הספרין מתאם מחיקה בכל כותבי האחסון:
|
||||
כותב אחסון וקטור: הסרת הטמעות ואינדקסים וקטוריים עבור המשתמש והאיסוף
|
||||
כותב אחסון אובייקטים: הסרת מסמכים וקבצים עבור המשתמש והאיסוף
|
||||
כותב triple store: הסרת נתוני גרף וטריפלים עבור המשתמש והאיסוף
|
||||
3. **ניקוי מטא-נתונים**: הסרת רשומת מטא-נתונים של איסוף מ-Cassandra
|
||||
4. **טיפול בשגיאות**: אם מחיקת אחסון כלשהי נכשלת, שמירה על עקביות באמצעות ביטול או מנגנוני ניסיון חוזר
|
||||
|
||||
#### ממשק ניהול איסופים
|
||||
|
||||
**⚠️ גישה מיושנת - הוחלפה בדפוס מבוסס תצורה**
|
||||
|
||||
הארכיטקטורה המבוססת על תורים המתוארת להלן הוחלפה בגישה מבוססת תצורה באמצעות `CollectionConfigHandler`. כל ה-backends אחסון מקבלים כעת עדכוני איסופים באמצעות הודעות דחיפה לתצורה במקום תורי ניהול ייעודיים.
|
||||
|
||||
~~כל כותבי האחסון מיישמים ממשק ניהול איסופים סטנדרטי עם סכימה משותפת:~~
|
||||
|
||||
~~**סכימת הודעה (`StorageManagementRequest`):**~~
|
||||
```json
|
||||
{
|
||||
"operation": "create-collection" | "delete-collection",
|
||||
"user": "user123",
|
||||
"collection": "documents-2024"
|
||||
}
|
||||
```
|
||||
|
||||
~~**ארכיטקטורת תורים:**~~
|
||||
~~**תור ניהול מאגרי וקטורים** (`vector-storage-management`): מאגרי וקטורים/הטבעות~~
|
||||
~~**תור ניהול אחסון אובייקטים** (`object-storage-management`): אחסון אובייקטים/מסמכים~~
|
||||
~~**תור ניהול מאגרי טריפל** (`triples-storage-management`): מאגרי גרפים/RDF~~
|
||||
~~**תור תגובות אחסון** (`storage-management-response`): כל התגובות נשלחות לכאן~~
|
||||
|
||||
**יישום נוכחי:**
|
||||
|
||||
כל מערכות האחסון משתמשות כעת ב-`CollectionConfigHandler`:
|
||||
**אינטגרציה של דחיפת תצורה**: שירותי אחסון נרשמים לקבלת התראות על שינויי תצורה
|
||||
**סנכרון אוטומטי**: אוספים נוצרים/נמחקים בהתבסס על שינויי תצורה
|
||||
**מודל הצהרתי**: אוספים מוגדרים בשירות התצורה, מערכות האחסון מסתנכרנות כדי להתאים
|
||||
**ללא בקשות/תגובות**: מבטל את התקורה של תיאום ומעקב אחר תגובות
|
||||
**מעקב אחר מצב אוסף**: נשמר באמצעות מטמון `known_collections`
|
||||
**פעולות אידמפוטנטיות**: בטוח לעבד את אותה תצורה מספר פעמים
|
||||
|
||||
כל מערכת אחסון מיישמת:
|
||||
`create_collection(user: str, collection: str, metadata: dict)` - יצירת מבני אוסף
|
||||
`delete_collection(user: str, collection: str)` - הסרת כל נתוני האוסף
|
||||
`collection_exists(user: str, collection: str) -> bool` - אימות לפני כתיבה
|
||||
|
||||
#### שינוי מבנה מאגר טריפל של Cassandra
|
||||
|
||||
כחלק מיישום זה, מאגר הטריפל של Cassandra ישונה ממודל של טבלה לכל אוסף למודל טבלה מאוחדת:
|
||||
|
||||
**ארכיטקטורה נוכחית:**
|
||||
מרחב מפתחות לכל משתמש, טבלה נפרדת לכל אוסף
|
||||
סכימה: `(s, p, o)` עם `PRIMARY KEY (s, p, o)`
|
||||
שמות טבלאות: אוספי משתמשים הופכים לטבלאות Cassandra נפרדות
|
||||
|
||||
**ארכיטקטורה חדשה:**
|
||||
מרחב מפתחות לכל משתמש, טבלה יחידה בשם "triples" לכל האוספים
|
||||
סכימה: `(collection, s, p, o)` עם `PRIMARY KEY (collection, s, p, o)`
|
||||
בידוד אוספים באמצעות חלוקה לאוספים
|
||||
|
||||
**שינויים נדרשים:**
|
||||
|
||||
1. **שינוי מבנה מחלקה TrustGraph** (`trustgraph/direct/cassandra.py`):
|
||||
הסרת פרמטר `table` מהקונסטרוקטור, שימוש בטבלה קבועה "triples"
|
||||
הוספת פרמטר `collection` לכל השיטות
|
||||
עדכון הסכימה כדי לכלול את האוסף בעמודה הראשונה
|
||||
**עדכוני אינדקסים**: ייוצרו אינדקסים חדשים לתמיכה בכל 8 דפוסי השאילתות:
|
||||
אינדקס על `(s)` עבור שאילתות מבוססות סובייקט
|
||||
אינדקס על `(p)` עבור שאילתות מבוססות פרידיקט
|
||||
אינדקס על `(o)` עבור שאילתות מבוססות אובייקט
|
||||
הערה: Cassandra אינה תומכת באינדקסים משניים רב-עמודתיים, לכן אלו הם אינדקסים בעמודה יחידה
|
||||
|
||||
**ביצועי דפוסי שאילתות:**
|
||||
✅ `get_all()` - סריקת מחיצה על `collection`
|
||||
✅ `get_s(s)` - משתמשת ביעילות במפתח ראשי (`collection, s`)
|
||||
✅ `get_p(p)` - משתמשת ב-`idx_p` עם סינון `collection`
|
||||
✅ `get_o(o)` - משתמשת ב-`idx_o` עם סינון `collection`
|
||||
✅ `get_sp(s, p)` - משתמשת ביעילות במפתח ראשי (`collection, s, p`)
|
||||
⚠️ `get_po(p, o)` - דורשת `ALLOW FILTERING` (משתמשת או ב-`idx_p` או ב-`idx_o` בתוספת סינון)
|
||||
✅ `get_os(o, s)` - משתמשת ב-`idx_o` עם סינון נוסף על `s`
|
||||
✅ `get_spo(s, p, o)` - משתמשת ביעילות במפתח ראשי מלא
|
||||
|
||||
**הערה על ALLOW FILTERING**: דפוס השאילתה `get_po` דורש `ALLOW FILTERING` מכיוון שהוא זקוק גם לאילוצי פרידיקט וגם לאובייקט ללא אינדקס מורכב מתאים. זה מקובל מכיוון שדפוס השאילתה הזה פחות נפוץ משאילתות מבוססות סובייקט בשימוש טיפוסי במאגר טריפל.
|
||||
|
||||
2. **עדכוני כותב אחסון** (`trustgraph/storage/triples/cassandra/write.py`):
|
||||
שמירה על חיבור TrustGraph יחיד לכל משתמש במקום לכל (משתמש, אוסף)
|
||||
העברת האוסף לפעולות הכנסה
|
||||
שיפור ניצול משאבים עם פחות חיבורים
|
||||
|
||||
3. **עדכוני שירות שאילתות** (`trustgraph/query/triples/cassandra/service.py`):
|
||||
חיבור TrustGraph יחיד לכל משתמש
|
||||
העברת האוסף לכל פעולות השאילתה
|
||||
שמירה על לוגיקת שאילתה זהה עם פרמטר האוסף
|
||||
|
||||
**יתרונות:**
|
||||
**מחיקת אוספים מפושטת:** מחיקה באמצעות מפתח מחיצה `collection` בכל 4 הטבלאות
|
||||
**יעילות משאבים:** פחות חיבורי מסד נתונים ואובייקטי טבלה
|
||||
**פעולות חוצות אוספים:** קל יותר ליישם פעולות המשתרעות על פני מספר אוספים
|
||||
**ארכיטקטורה עקבית:** מתאימה לגישה מאוחדת למטא-נתונים של אוספים
|
||||
**אימות אוסף:** קל לבדוק את קיום האוסף באמצעות טבלת `triples_collection`
|
||||
|
||||
פעולות איסוף יהיו אטומיות במידת האפשר, ויספקו טיפול בשגיאות ואימות מתאימים.
|
||||
|
||||
## שיקולי אבטחה
|
||||
|
||||
פעולות ניהול איסוף דורשות הרשאות מתאימות כדי למנוע גישה או מחיקה לא מורשית של איסופים. בקרת הגישה תתאים למודלי האבטחה הקיימים של TrustGraph.
|
||||
|
||||
## שיקולי ביצועים
|
||||
|
||||
פעולות הצגת איסופים עשויות לדרוש דפוס של חלוקה לדפים (pagination) עבור סביבות עם מספר גדול של איסופים. שאילתות מטא-נתונים צריכות להיות מותאמות לשיטות סינון נפוצות.
|
||||
|
||||
## אסטרטגיית בדיקות
|
||||
|
||||
בדיקות מקיפות יכסו:
|
||||
זרימת עבודה של יצירת איסוף מקצה לקצה
|
||||
סנכרון עם ה-backend של האחסון
|
||||
אימות כתיבה עבור איסופים שאינם קיימים
|
||||
טיפול בשאילתות עבור איסופים שאינם קיימים
|
||||
מחיקת איסוף עם השפעה על כל האחסונים
|
||||
טיפול בשגיאות ותסריטי התאוששות
|
||||
בדיקות יחידה עבור כל ה-backend של האחסון
|
||||
בדיקות אינטגרציה עבור פעולות חוצות-אחסונים
|
||||
|
||||
## סטטוס יישום
|
||||
|
||||
### ✅ רכיבים שהושלמו
|
||||
|
||||
1. **שירות ניהול איסופים של Librarian** (`trustgraph-flow/trustgraph/librarian/collection_manager.py`)
|
||||
פעולות CRUD של מטא-נתונים של איסוף (רשימה, עדכון, מחיקה)
|
||||
שילוב עם טבלת מטא-נתונים של איסוף ב-Cassandra באמצעות `LibraryTableStore`
|
||||
תיאום מחיקת איסוף עם השפעה על כל סוגי האחסון
|
||||
טיפול בבקשות/תגובות אסינכרוניות עם ניהול שגיאות מתאים
|
||||
|
||||
2. **סכימת מטא-נתונים של איסוף** (`trustgraph-base/trustgraph/schema/services/collection.py`)
|
||||
סכימות `CollectionManagementRequest` ו-`CollectionManagementResponse`
|
||||
סכימה `CollectionMetadata` עבור רשומות איסוף
|
||||
הגדרות נושא תורים עבור בקשות/תגובות של איסוף
|
||||
|
||||
3. **סכימת ניהול אחסון** (`trustgraph-base/trustgraph/schema/services/storage.py`)
|
||||
סכימות `StorageManagementRequest` ו-`StorageManagementResponse`
|
||||
נושאים של תורי ניהול אחסון הוגדרו
|
||||
פורמט הודעה עבור פעולות של איסוף ברמת האחסון
|
||||
|
||||
4. **סכימת 4-טבלאות של Cassandra** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py`)
|
||||
מפתחות מחיצה מורכבים לביצועי שאילתה
|
||||
טבלה `triples_collection` עבור שאילתות SPO ומעקב אחר מחיקה
|
||||
יישום מחיקת איסוף עם דפוס של קריאה ולאחר מכן מחיקה
|
||||
|
||||
### ✅ מעבר לדפוס מבוסס תצורה - הושלם
|
||||
|
||||
**כל ה-backend של האחסון עברו מדפוס מבוסס תורים לדפוס מבוסס תצורה `CollectionConfigHandler`.**
|
||||
|
||||
מעברים שהושלמו:
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/neo4j/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/memgraph/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/falkordb/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
|
||||
כל ה-backend כעת:
|
||||
יורשים מ-`CollectionConfigHandler`
|
||||
נרשמים לקבלת הודעות דחיפה של תצורה באמצעות `self.register_config_handler(self.on_collection_config)`
|
||||
מיישמים `create_collection(user, collection, metadata)` ו-`delete_collection(user, collection)`
|
||||
משתמשים ב-`collection_exists(user, collection)` לאימות לפני כתיבה
|
||||
מסתנכרנים באופן אוטומטי עם שינויים בשירות התצורה
|
||||
|
||||
תשתית מבוססת תורים ישנה הוסרה:
|
||||
✅ הוסרו סכימות `StorageManagementRequest` ו-`StorageManagementResponse`
|
||||
✅ הוסרו הגדרות נושאים של תורי ניהול אחסון
|
||||
✅ הוסר צרכן/מפיק תורים מכל ה-backend
|
||||
✅ הוסרו מטפלים `on_storage_management` מכל ה-backend
|
||||
410
docs/tech-specs/collection-management.hi.md
Normal file
410
docs/tech-specs/collection-management.hi.md
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
---
|
||||
layout: default
|
||||
title: "संग्रह प्रबंधन तकनीकी विनिर्देश"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# संग्रह प्रबंधन तकनीकी विनिर्देश
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## अवलोकन
|
||||
|
||||
यह विनिर्देश ट्रस्टग्राफ के लिए संग्रह प्रबंधन क्षमताओं का वर्णन करता है, जिसमें स्पष्ट संग्रह निर्माण की आवश्यकता होती है और संग्रह जीवनचक्र पर प्रत्यक्ष नियंत्रण प्रदान किया जाता है। उपयोग से पहले संग्रहों को स्पष्ट रूप से बनाया जाना चाहिए, जिससे लाइब्रेरियन मेटाडेटा और सभी स्टोरेज बैकएंड के बीच उचित सिंक्रोनाइज़ेशन सुनिश्चित हो सके। यह सुविधा चार प्राथमिक उपयोग मामलों का समर्थन करती है:
|
||||
|
||||
1. **संग्रह निर्माण**: डेटा संग्रहीत करने से पहले स्पष्ट रूप से संग्रह बनाएं
|
||||
2. **संग्रह सूची**: सिस्टम में सभी मौजूदा संग्रह देखें
|
||||
3. **संग्रह मेटाडेटा प्रबंधन**: संग्रह नामों, विवरणों और टैगों को अपडेट करें
|
||||
4. **संग्रह विलोपन**: संग्रह और उनके संबंधित डेटा को सभी स्टोरेज प्रकारों से हटा दें
|
||||
|
||||
## लक्ष्य
|
||||
|
||||
**स्पष्ट संग्रह निर्माण**: डेटा संग्रहीत करने से पहले संग्रह बनाए जाने की आवश्यकता होती है
|
||||
**स्टोरेज सिंक्रोनाइज़ेशन**: सुनिश्चित करें कि संग्रह सभी स्टोरेज बैकएंड (वेक्टर, ऑब्जेक्ट, ट्रिपल) में मौजूद हैं
|
||||
**संग्रह दृश्यता**: उपयोगकर्ताओं को अपने वातावरण में सभी संग्रहों को सूचीबद्ध और निरीक्षण करने में सक्षम करें
|
||||
**संग्रह सफाई**: अब आवश्यक नहीं होने वाले संग्रहों को हटाने की अनुमति दें
|
||||
**संग्रह संगठन**: बेहतर संग्रह ट्रैकिंग और खोज के लिए लेबल और टैग का समर्थन करें
|
||||
**मेटाडेटा प्रबंधन**: परिचालन स्पष्टता के लिए संग्रहों के साथ सार्थक मेटाडेटा संबद्ध करें
|
||||
**संग्रह खोज**: फ़िल्टरिंग और खोज के माध्यम से विशिष्ट संग्रहों को खोजना आसान बनाएं
|
||||
**परिचालन पारदर्शिता**: संग्रह जीवनचक्र और उपयोग में स्पष्ट दृश्यता प्रदान करें
|
||||
**संसाधन प्रबंधन**: अप्रयुक्त संग्रहों को साफ करके संसाधन उपयोग को अनुकूलित करें
|
||||
**डेटा अखंडता**: स्टोरेज में मेटाडेटा ट्रैकिंग के बिना अनाथ संग्रहों को रोकें
|
||||
|
||||
## पृष्ठभूमि
|
||||
|
||||
पहले, ट्रस्टग्राफ में संग्रह डेटा लोडिंग कार्यों के दौरान निहित रूप से बनाए जाते थे, जिससे सिंक्रोनाइज़ेशन संबंधी समस्याएं होती थीं, जहाँ संग्रह स्टोरेज बैकएंड में मौजूद हो सकते थे लेकिन लाइब्रेरियन में संबंधित मेटाडेटा नहीं होता था। इससे प्रबंधन में चुनौतियां और संभावित अनाथ डेटा उत्पन्न होता था।
|
||||
|
||||
स्पष्ट संग्रह निर्माण मॉडल इन मुद्दों को संबोधित करता है:
|
||||
`tg-set-collection` के माध्यम से उपयोग से पहले संग्रह बनाने की आवश्यकता होती है
|
||||
सभी स्टोरेज बैकएंड में संग्रह निर्माण का प्रसारण
|
||||
लाइब्रेरियन मेटाडेटा और स्टोरेज के बीच सिंक्रोनाइज़ स्थिति बनाए रखना
|
||||
गैर-मौजूदा संग्रहों में लेखन को रोकना
|
||||
स्पष्ट संग्रह जीवनचक्र प्रबंधन प्रदान करना
|
||||
|
||||
यह विनिर्देश स्पष्ट संग्रह प्रबंधन मॉडल को परिभाषित करता है। स्पष्ट संग्रह निर्माण की आवश्यकता करके, ट्रस्टग्राफ यह सुनिश्चित करता है:
|
||||
संग्रह निर्माण से लाइब्रेरियन मेटाडेटा में ट्रैक किए जाते हैं
|
||||
सभी स्टोरेज बैकएंड डेटा प्राप्त करने से पहले संग्रहों के बारे में जानते हैं
|
||||
स्टोरेज में कोई अनाथ संग्रह नहीं है
|
||||
संग्रह जीवनचक्र पर स्पष्ट परिचालन दृश्यता और नियंत्रण
|
||||
गैर-मौजूदा संग्रहों को संदर्भित करने वाले कार्यों के लिए सुसंगत त्रुटि हैंडलिंग
|
||||
|
||||
## तकनीकी डिजाइन
|
||||
|
||||
### वास्तुकला
|
||||
|
||||
संग्रह प्रबंधन प्रणाली को मौजूदा ट्रस्टग्राफ बुनियादी ढांचे के भीतर लागू किया जाएगा:
|
||||
|
||||
1. **लाइब्रेरियन सेवा एकीकरण**
|
||||
संग्रह प्रबंधन संचालन मौजूदा लाइब्रेरियन सेवा में जोड़े जाएंगे
|
||||
किसी नई सेवा की आवश्यकता नहीं है - मौजूदा प्रमाणीकरण और एक्सेस पैटर्न का लाभ उठाता है
|
||||
संग्रह सूची, विलोपन और मेटाडेटा प्रबंधन को संभालता है
|
||||
|
||||
मॉड्यूल: trustgraph-librarian
|
||||
|
||||
2. **कैसेंड्रा संग्रह मेटाडेटा तालिका**
|
||||
मौजूदा लाइब्रेरियन कीस्पेस में एक नई तालिका
|
||||
उपयोगकर्ता-स्कोप किए गए एक्सेस के साथ संग्रह मेटाडेटा संग्रहीत करता है
|
||||
प्राथमिक कुंजी: उचित मल्टी-टेनेंसी के लिए (user_id, collection_id)
|
||||
|
||||
मॉड्यूल: trustgraph-librarian
|
||||
|
||||
3. **संग्रह प्रबंधन CLI**
|
||||
संग्रह संचालन के लिए कमांड-लाइन इंटरफ़ेस
|
||||
सूची, हटाएं, लेबल और टैग प्रबंधन कमांड प्रदान करता है
|
||||
मौजूदा CLI फ्रेमवर्क के साथ एकीकृत
|
||||
|
||||
मॉड्यूल: trustgraph-cli
|
||||
|
||||
### डेटा मॉडल
|
||||
|
||||
#### कैसेंड्रा संग्रह मेटाडेटा तालिका
|
||||
|
||||
संग्रह मेटाडेटा को लाइब्रेरियन कीस्पेस में एक संरचित कैसेंड्रा तालिका में संग्रहीत किया जाएगा:
|
||||
|
||||
```sql
|
||||
CREATE TABLE collections (
|
||||
user text,
|
||||
collection text,
|
||||
name text,
|
||||
description text,
|
||||
tags set<text>,
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
PRIMARY KEY (user, collection)
|
||||
);
|
||||
```
|
||||
|
||||
तालिका संरचना:
|
||||
**user**: **collection**: समग्र प्राथमिक कुंजी जो उपयोगकर्ता अलगाव सुनिश्चित करती है
|
||||
**name**: संग्रह का मानव-पठनीय नाम
|
||||
**description**: संग्रह के उद्देश्य का विस्तृत विवरण
|
||||
**tags**: वर्गीकरण और फ़िल्टरिंग के लिए टैग का सेट
|
||||
**created_at**: संग्रह निर्माण का टाइमस्टैम्प
|
||||
**updated_at**: अंतिम संशोधन टाइमस्टैम्प
|
||||
|
||||
यह दृष्टिकोण अनुमति देता है:
|
||||
उपयोगकर्ता अलगाव के साथ बहु-किरायेदार संग्रह प्रबंधन
|
||||
उपयोगकर्ता और संग्रह द्वारा कुशल क्वेरी
|
||||
संगठन के लिए लचीला टैगिंग सिस्टम
|
||||
परिचालन अंतर्दृष्टि के लिए जीवनचक्र ट्रैकिंग
|
||||
|
||||
#### संग्रह जीवनचक्र
|
||||
|
||||
डेटा संचालन शुरू करने से पहले संग्रह को स्पष्ट रूप से लाइब्रेरियन में बनाया जाना चाहिए:
|
||||
|
||||
1. **संग्रह निर्माण** (दो रास्ते):
|
||||
|
||||
**रास्ता A: उपयोगकर्ता-आरंभित निर्माण** `tg-set-collection` के माध्यम से:
|
||||
उपयोगकर्ता संग्रह आईडी, नाम, विवरण और टैग प्रदान करता है
|
||||
लाइब्रेरियन `collections` तालिका में मेटाडेटा रिकॉर्ड बनाता है
|
||||
लाइब्रेरियन सभी स्टोरेज बैकएंड पर "create-collection" प्रसारित करता है
|
||||
सभी स्टोरेज प्रोसेसर संग्रह बनाते हैं और सफलता की पुष्टि करते हैं
|
||||
संग्रह अब डेटा संचालन के लिए तैयार है
|
||||
|
||||
**रास्ता B: दस्तावेज़ सबमिशन पर स्वचालित निर्माण**:
|
||||
उपयोगकर्ता एक संग्रह आईडी निर्दिष्ट करते हुए एक दस्तावेज़ सबमिट करता है
|
||||
लाइब्रेरियन जांचता है कि क्या संग्रह मेटाडेटा तालिका में मौजूद है
|
||||
यदि मौजूद नहीं है: लाइब्रेरियन डिफ़ॉल्ट के साथ मेटाडेटा बनाता है (नाम = संग्रह_आईडी, खाली विवरण/टैग)
|
||||
लाइब्रेरियन सभी स्टोरेज बैकएंड पर "create-collection" प्रसारित करता है
|
||||
सभी स्टोरेज प्रोसेसर संग्रह बनाते हैं और सफलता की पुष्टि करते हैं
|
||||
दस्तावेज़ प्रसंस्करण संग्रह स्थापित होने के साथ आगे बढ़ता है
|
||||
|
||||
दोनों रास्ते यह सुनिश्चित करते हैं कि संग्रह लाइब्रेरियन मेटाडेटा में और सभी स्टोरेज बैकएंड में मौजूद है, डेटा संचालन से पहले।
|
||||
|
||||
2. **भंडारण सत्यापन**: लेखन संचालन संग्रह के अस्तित्व को मान्य करते हैं:
|
||||
स्टोरेज प्रोसेसर लेखन स्वीकार करने से पहले संग्रह की स्थिति की जांच करते हैं
|
||||
गैर-मौजूदा संग्रह में लेखन त्रुटि लौटाते हैं
|
||||
यह लाइब्रेरियन के संग्रह निर्माण तर्क को बायपास करने वाले सीधे लेखन को रोकता है
|
||||
|
||||
3. **क्वेरी व्यवहार**: क्वेरी संचालन गैर-मौजूदा संग्रह को सुचारू रूप से संभालते हैं:
|
||||
गैर-मौजूदा संग्रह में क्वेरी खाली परिणाम लौटाती है
|
||||
कोई त्रुटि नहीं फेंकी जाती है क्वेरी संचालन के लिए
|
||||
संग्रह के मौजूद होने की आवश्यकता के बिना अन्वेषण की अनुमति देता है
|
||||
|
||||
4. **मेटाडेटा अपडेट**: उपयोगकर्ता निर्माण के बाद संग्रह मेटाडेटा को अपडेट कर सकते हैं:
|
||||
`tg-set-collection` के माध्यम से नाम, विवरण और टैग अपडेट करें
|
||||
अपडेट केवल लाइब्रेरियन मेटाडेटा पर लागू होते हैं
|
||||
स्टोरेज बैकएंड संग्रह बनाए रखते हैं लेकिन मेटाडेटा अपडेट प्रसारित नहीं होते हैं
|
||||
|
||||
5. **स्पष्ट विलोपन**: उपयोगकर्ता `tg-delete-collection` के माध्यम से संग्रह को हटाते हैं:
|
||||
लाइब्रेरियन सभी स्टोरेज बैकएंड पर "delete-collection" प्रसारित करता है
|
||||
सभी स्टोरेज प्रोसेसर से पुष्टिकरण की प्रतीक्षा करता है
|
||||
केवल स्टोरेज क्लीनअप पूरा होने के बाद लाइब्रेरियन मेटाडेटा रिकॉर्ड को हटाता है
|
||||
यह सुनिश्चित करता है कि कोई भी डेटा स्टोरेज में नहीं बचा है
|
||||
|
||||
**मुख्य सिद्धांत**: लाइब्रेरियन संग्रह निर्माण के लिए एकल नियंत्रण बिंदु है। चाहे उपयोगकर्ता कमांड द्वारा शुरू किया गया हो या दस्तावेज़ सबमिशन द्वारा, लाइब्रेरियन डेटा संचालन की अनुमति देने से पहले उचित मेटाडेटा ट्रैकिंग और स्टोरेज बैकएंड सिंक्रोनाइज़ेशन सुनिश्चित करता है।
|
||||
|
||||
आवश्यक संचालन:
|
||||
**संग्रह बनाएं**: `tg-set-collection` के माध्यम से उपयोगकर्ता ऑपरेशन या दस्तावेज़ सबमिशन पर स्वचालित
|
||||
**संग्रह मेटाडेटा अपडेट करें**: नाम, विवरण और टैग को संशोधित करने के लिए उपयोगकर्ता ऑपरेशन
|
||||
**संग्रह हटाएं**: सभी स्टोर में संग्रह और उसके डेटा को हटाने के लिए उपयोगकर्ता ऑपरेशन
|
||||
**संग्रह सूचीबद्ध करें**: टैग द्वारा फ़िल्टर करके संग्रह देखने के लिए उपयोगकर्ता ऑपरेशन
|
||||
|
||||
#### मल्टी-स्टोर संग्रह प्रबंधन
|
||||
|
||||
संग्रह ट्रस्टग्राफ में कई स्टोरेज बैकएंड में मौजूद हैं:
|
||||
**वेक्टर स्टोर** (Qdrant, Milvus, Pinecone): एम्बेडिंग और वेक्टर डेटा संग्रहीत करें
|
||||
**ऑब्जेक्ट स्टोर** (Cassandra): दस्तावेज़ और फ़ाइल डेटा संग्रहीत करें
|
||||
**ट्रिपल स्टोर** (Cassandra, Neo4j, Memgraph, FalkorDB): ग्राफ/RDF डेटा संग्रहीत करें
|
||||
|
||||
प्रत्येक स्टोर प्रकार निम्नलिखित लागू करता है:
|
||||
**संग्रह स्थिति ट्रैकिंग**: यह जानकारी बनाए रखें कि कौन से संग्रह मौजूद हैं
|
||||
**संग्रह निर्माण**: "संग्रह बनाएं" संचालन स्वीकार करें और संसाधित करें
|
||||
**संग्रह सत्यापन**: लिखने को स्वीकार करने से पहले जांचें कि संग्रह मौजूद है या नहीं
|
||||
**संग्रह विलोपन**: निर्दिष्ट संग्रह के लिए सभी डेटा हटाएं
|
||||
|
||||
लाइब्रेरियन सेवा सभी स्टोर प्रकारों में संग्रह संचालन का समन्वय करती है, यह सुनिश्चित करते हुए:
|
||||
सभी बैकएंड में संग्रह का निर्माण उपयोग से पहले किया जाता है
|
||||
सभी बैकएंड निर्माण की पुष्टि करते हैं इससे पहले कि सफलता वापस की जाए
|
||||
भंडारण प्रकारों में संग्रह जीवनचक्र का सिंक्रनाइज़ेशन
|
||||
जब संग्रह मौजूद नहीं होते हैं तो सुसंगत त्रुटि हैंडलिंग
|
||||
|
||||
#### संग्रहण स्थिति ट्रैकिंग, संग्रहण प्रकार द्वारा
|
||||
|
||||
प्रत्येक संग्रहण बैकएंड अपनी क्षमताओं के आधार पर संग्रह स्थिति को अलग-अलग तरीके से ट्रैक करता है:
|
||||
|
||||
**कैसेंड्रा ट्रिपल स्टोर:**
|
||||
मौजूदा `triples_collection` तालिका का उपयोग करता है
|
||||
संग्रह बनने पर सिस्टम मार्कर ट्रिपल बनाता है
|
||||
क्वेरी: `SELECT collection FROM triples_collection WHERE collection = ? LIMIT 1`
|
||||
संग्रह के अस्तित्व की जांच के लिए कुशल सिंगल-पार्टिशन चेक
|
||||
|
||||
**Qdrant/Milvus/Pinecone वेक्टर स्टोर:**
|
||||
मूल संग्रह एपीआई अस्तित्व जांच प्रदान करते हैं
|
||||
उचित वेक्टर कॉन्फ़िगरेशन के साथ संग्रह बनाए जाते हैं
|
||||
`collection_exists()` विधि संग्रहण एपीआई का उपयोग करती है
|
||||
संग्रह निर्माण आयाम आवश्यकताओं को मान्य करता है
|
||||
|
||||
**Neo4j/Memgraph/FalkorDB ग्राफ स्टोर:**
|
||||
संग्रह को ट्रैक करने के लिए `:CollectionMetadata` नोड्स का उपयोग करें
|
||||
नोड गुण: `{user, collection, created_at}`
|
||||
क्वेरी: `MATCH (c:CollectionMetadata {user: $user, collection: $collection})`
|
||||
डेटा नोड्स से अलग, स्पष्ट अलगाव के लिए
|
||||
कुशल संग्रह लिस्टिंग और सत्यापन को सक्षम करता है
|
||||
|
||||
**कैसेंड्रा ऑब्जेक्ट स्टोर:**
|
||||
संग्रह मेटाडेटा तालिका या मार्कर पंक्तियों का उपयोग करता है
|
||||
ट्रिपल स्टोर के समान पैटर्न
|
||||
दस्तावेज़ लेखन से पहले संग्रह को मान्य करता है
|
||||
|
||||
### एपीआई
|
||||
|
||||
संग्रह प्रबंधन एपीआई (लाइब्रेरियन):
|
||||
**संग्रह बनाएं/अपडेट करें**: `tg-set-collection` के माध्यम से एक नया संग्रह बनाएं या मौजूदा मेटाडेटा को अपडेट करें
|
||||
**संग्रह सूचीबद्ध करें**: वैकल्पिक टैग फ़िल्टरिंग के साथ एक उपयोगकर्ता के लिए संग्रह पुनर्प्राप्त करें
|
||||
**संग्रह हटाएं**: संग्रह और उससे जुड़े डेटा को हटाएं, सभी स्टोर प्रकारों में कैस्केड करें
|
||||
|
||||
संग्रहण प्रबंधन एपीआई (सभी संग्रहण प्रोसेसर):
|
||||
**संग्रह बनाएं**: "संग्रह बनाएं" ऑपरेशन को संभालें, संग्रहण में संग्रह स्थापित करें
|
||||
**संग्रह हटाएं**: "संग्रह हटाएं" ऑपरेशन को संभालें, सभी संग्रह डेटा को हटाएं
|
||||
**संग्रह मौजूद है जांच**: लेखन संचालन को स्वीकार करने से पहले आंतरिक सत्यापन
|
||||
|
||||
डेटा ऑपरेशन एपीआई (संशोधित व्यवहार):
|
||||
**लिखने एपीआई**: डेटा स्वीकार करने से पहले जांचें कि संग्रह मौजूद है या नहीं, यदि नहीं तो त्रुटि लौटाएं
|
||||
**क्वेरी एपीआई**: त्रुटि के बिना गैर-मौजूद संग्रह के लिए खाली परिणाम लौटाएं
|
||||
|
||||
### कार्यान्वयन विवरण
|
||||
|
||||
कार्यान्वयन सेवा एकीकरण और CLI कमांड संरचना के लिए मौजूदा ट्रस्टग्राफ पैटर्न का पालन करेगा।
|
||||
|
||||
#### संग्रह विलोपन कैस्केड
|
||||
|
||||
जब कोई उपयोगकर्ता लाइब्रेरियन सेवा के माध्यम से संग्रह विलोपन शुरू करता है:
|
||||
|
||||
1. **मेटाडेटा सत्यापन**: सत्यापित करें कि संग्रह मौजूद है और उपयोगकर्ता के पास हटाने की अनुमति है
|
||||
2. **स्टोर कैस्केड**: लाइब्रेरियन सभी स्टोर लेखकों में विलोपन का समन्वय करता है:
|
||||
वेक्टर स्टोर लेखक: उपयोगकर्ता और संग्रह के लिए एम्बेडिंग और वेक्टर इंडेक्स हटाएं
|
||||
ऑब्जेक्ट स्टोर लेखक: उपयोगकर्ता और संग्रह के लिए दस्तावेज़ और फ़ाइलें हटाएं
|
||||
ट्रिपल स्टोर लेखक: उपयोगकर्ता और संग्रह के लिए ग्राफ डेटा और ट्रिपल हटाएं
|
||||
3. **मेटाडेटा सफाई**: कैसेंड्रा से संग्रह मेटाडेटा रिकॉर्ड हटाएं
|
||||
4. **त्रुटि हैंडलिंग**: यदि किसी भी स्टोर विलोपन में विफलता होती है, तो रोलबैक या पुनः प्रयास तंत्र के माध्यम से स्थिरता बनाए रखें
|
||||
|
||||
#### संग्रह प्रबंधन इंटरफ़ेस
|
||||
|
||||
⚠️ लेगेसी अप्रोच - कॉन्फ़िग-आधारित पैटर्न द्वारा प्रतिस्थापित
|
||||
|
||||
नीचे वर्णित कतार-आधारित आर्किटेक्चर को `CollectionConfigHandler` का उपयोग करके एक कॉन्फ़िग-आधारित दृष्टिकोण से बदल दिया गया है। अब सभी संग्रहण बैकएंड समर्पित प्रबंधन कतारों के बजाय कॉन्फ़िग पुश संदेशों के माध्यम से संग्रह अपडेट प्राप्त करते हैं।
|
||||
|
||||
~~सभी स्टोर लेखक एक मानकीकृत संग्रह प्रबंधन इंटरफ़ेस को लागू करते हैं जिसमें एक सामान्य स्कीमा है:~~
|
||||
|
||||
~~**संदेश स्कीमा (`StorageManagementRequest`):~~
|
||||
```json
|
||||
{
|
||||
"operation": "create-collection" | "delete-collection",
|
||||
"user": "user123",
|
||||
"collection": "documents-2024"
|
||||
}
|
||||
```
|
||||
|
||||
~~**क्यू आर्किटेक्चर:**~~
|
||||
~~**वेक्टर स्टोर मैनेजमेंट क्यू** (`vector-storage-management`): वेक्टर/एम्बेडिंग स्टोर~~
|
||||
~~**ऑब्जेक्ट स्टोर मैनेजमेंट क्यू** (`object-storage-management`): ऑब्जेक्ट/डॉक्यूमेंट स्टोर~~
|
||||
~~**ट्रिपल स्टोर मैनेजमेंट क्यू** (`triples-storage-management`): ग्राफ/आरडीएफ स्टोर~~
|
||||
~~**स्टोरेज रिस्पांस क्यू** (`storage-management-response`): सभी प्रतिक्रियाएं यहां भेजी जाती हैं~~
|
||||
|
||||
**वर्तमान कार्यान्वयन:**
|
||||
|
||||
सभी स्टोरेज बैकएंड अब `CollectionConfigHandler` का उपयोग करते हैं:
|
||||
**कॉन्फ़िग पुश इंटीग्रेशन**: स्टोरेज सेवाएं कॉन्फ़िग पुश नोटिफिकेशन के लिए पंजीकरण करती हैं
|
||||
**स्वचालित सिंक्रोनाइज़ेशन**: कॉन्फ़िग परिवर्तनों के आधार पर संग्रह बनाए/हटाए जाते हैं
|
||||
**घोषणात्मक मॉडल**: संग्रह कॉन्फ़िग सेवा में परिभाषित हैं, बैकएंड मिलान के लिए सिंक्रोनाइज़ होते हैं
|
||||
**कोई अनुरोध/प्रतिक्रिया नहीं**: समन्वय ओवरहेड और प्रतिक्रिया ट्रैकिंग को समाप्त करता है
|
||||
**संग्रह स्थिति ट्रैकिंग**: `known_collections` कैश के माध्यम से बनाए रखा जाता है
|
||||
**आइडेंपोटेंट ऑपरेशन**: एक ही कॉन्फ़िग को कई बार संसाधित करना सुरक्षित है
|
||||
|
||||
प्रत्येक स्टोरेज बैकएंड लागू करता है:
|
||||
`create_collection(user: str, collection: str, metadata: dict)` - संग्रह संरचनाएं बनाएं
|
||||
`delete_collection(user: str, collection: str)` - सभी संग्रह डेटा हटाएं
|
||||
`collection_exists(user: str, collection: str) -> bool` - लिखने से पहले मान्य करें
|
||||
|
||||
#### कैसेंड्रा ट्रिपल स्टोर रीफैक्टर
|
||||
|
||||
इस कार्यान्वयन के हिस्से के रूप में, कैसेंड्रा ट्रिपल स्टोर को एक टेबल-प्रति-संग्रह मॉडल से एक एकीकृत टेबल मॉडल में रीफैक्टर किया जाएगा:
|
||||
|
||||
**वर्तमान आर्किटेक्चर:**
|
||||
प्रति उपयोगकर्ता की स्पेस, प्रत्येक संग्रह के लिए अलग टेबल
|
||||
स्कीमा: `(s, p, o)` with `PRIMARY KEY (s, p, o)`
|
||||
टेबल नाम: उपयोगकर्ता संग्रह अलग-अलग कैसेंड्रा टेबल बन जाते हैं
|
||||
|
||||
**नया आर्किटेक्चर:**
|
||||
प्रति उपयोगकर्ता की स्पेस, सभी संग्रहों के लिए एक सिंगल "ट्रिपल्स" टेबल
|
||||
स्कीमा: `(collection, s, p, o)` with `PRIMARY KEY (collection, s, p, o)`
|
||||
संग्रह विभाजन के माध्यम से संग्रह अलगाव
|
||||
|
||||
**आवश्यक परिवर्तन:**
|
||||
|
||||
1. **ट्रस्टग्राफ क्लास रीफैक्टर** (`trustgraph/direct/cassandra.py`):
|
||||
कंस्ट्रक्टर से `table` पैरामीटर हटाएं, फिक्स्ड "ट्रिपल्स" टेबल का उपयोग करें
|
||||
सभी विधियों में `collection` पैरामीटर जोड़ें
|
||||
स्कीमा को संग्रह को पहले कॉलम के रूप में शामिल करने के लिए अपडेट करें
|
||||
**इंडेक्स अपडेट**: सभी 8 क्वेरी पैटर्न का समर्थन करने के लिए नए इंडेक्स बनाए जाएंगे:
|
||||
विषय-आधारित प्रश्नों के लिए `(s)` पर इंडेक्स
|
||||
विधेय-आधारित प्रश्नों के लिए `(p)` पर इंडेक्स
|
||||
ऑब्जेक्ट-आधारित प्रश्नों के लिए `(o)` पर इंडेक्स
|
||||
ध्यान दें: कैसेंड्रा मल्टी-कॉलम सेकेंडरी इंडेक्स का समर्थन नहीं करता है, इसलिए ये सिंगल-कॉलम इंडेक्स हैं
|
||||
|
||||
**क्वेरी पैटर्न प्रदर्शन:**
|
||||
✅ `get_all()` - `collection` पर विभाजन स्कैन
|
||||
✅ `get_s(s)` - प्राथमिक कुंजी का कुशलतापूर्वक उपयोग करता है (`collection, s`)
|
||||
✅ `get_p(p)` - `idx_p` का उपयोग `collection` फ़िल्टरिंग के साथ
|
||||
✅ `get_o(o)` - `idx_o` का उपयोग `collection` फ़िल्टरिंग के साथ
|
||||
✅ `get_sp(s, p)` - प्राथमिक कुंजी का कुशलतापूर्वक उपयोग करता है (`collection, s, p`)
|
||||
⚠️ `get_po(p, o)` - `ALLOW FILTERING` की आवश्यकता है (या तो `idx_p` या `idx_o` प्लस फ़िल्टरिंग का उपयोग करता है)
|
||||
✅ `get_os(o, s)` - `idx_o` का उपयोग अतिरिक्त फ़िल्टरिंग के साथ `s` पर
|
||||
✅ `get_spo(s, p, o)` - पूरी प्राथमिक कुंजी का कुशलतापूर्वक उपयोग करता है
|
||||
|
||||
**ALLOW FILTERING पर नोट:** `get_po` क्वेरी पैटर्न को `ALLOW FILTERING` की आवश्यकता होती है क्योंकि इसे उपयुक्त कंपाउंड इंडेक्स के बिना विधेय और ऑब्जेक्ट बाधाओं दोनों की आवश्यकता होती है। यह स्वीकार्य है क्योंकि यह क्वेरी पैटर्न विशिष्ट ट्रिपल स्टोर उपयोग में विषय-आधारित प्रश्नों की तुलना में कम सामान्य है
|
||||
|
||||
2. **स्टोरेज राइटर अपडेट** (`trustgraph/storage/triples/cassandra/write.py`):
|
||||
प्रति (उपयोगकर्ता, संग्रह) के बजाय प्रति उपयोगकर्ता सिंगल ट्रस्टग्राफ कनेक्शन बनाए रखें
|
||||
सम्मिलित कार्यों में संग्रह पास करें
|
||||
कम कनेक्शन के साथ बेहतर संसाधन उपयोग
|
||||
|
||||
3. **क्वेरी सर्विस अपडेट** (`trustgraph/query/triples/cassandra/service.py`):
|
||||
प्रति उपयोगकर्ता सिंगल ट्रस्टग्राफ कनेक्शन
|
||||
सभी क्वेरी कार्यों में संग्रह पास करें
|
||||
संग्रह पैरामीटर के साथ समान क्वेरी लॉजिक बनाए रखें
|
||||
|
||||
**लाभ:**
|
||||
**सरलीकृत संग्रह विलोपन:** सभी 4 तालिकाओं में `collection` विभाजन कुंजी का उपयोग करके हटाएं
|
||||
**संसाधन दक्षता:** कम डेटाबेस कनेक्शन और टेबल ऑब्जेक्ट
|
||||
**क्रॉस-संग्रह संचालन:** कई संग्रहों को कवर करने वाले संचालन को लागू करना आसान है
|
||||
**संगत आर्किटेक्चर:** एकीकृत संग्रह मेटाडेटा दृष्टिकोण के साथ संरेखित
|
||||
**संग्रह सत्यापन:** `triples_collection` टेबल के माध्यम से संग्रह अस्तित्व की जांच करना आसान है
|
||||
|
||||
संग्रह संचालन संभव होने पर परमाणु होंगे और उचित त्रुटि प्रबंधन और सत्यापन प्रदान करेंगे।
|
||||
|
||||
## सुरक्षा संबंधी विचार
|
||||
|
||||
संग्रह प्रबंधन कार्यों के लिए उचित प्राधिकरण की आवश्यकता होती है ताकि अनधिकृत पहुंच या संग्रहों के हटाने को रोका जा सके। पहुंच नियंत्रण मौजूदा ट्रस्टग्राफ सुरक्षा मॉडल के अनुरूप होगा।
|
||||
|
||||
## प्रदर्शन संबंधी विचार
|
||||
|
||||
बड़ी संख्या में संग्रहों वाले वातावरण में संग्रह सूची संचालन के लिए पेजिंग की आवश्यकता हो सकती है। सामान्य फ़िल्टरिंग पैटर्न के लिए मेटाडेटा प्रश्नों को अनुकूलित किया जाना चाहिए।
|
||||
|
||||
## परीक्षण रणनीति
|
||||
|
||||
व्यापक परीक्षण में शामिल होंगे:
|
||||
संग्रह निर्माण वर्कफ़्लो का एंड-टू-एंड परीक्षण
|
||||
स्टोरेज बैकएंड सिंक्रोनाइज़ेशन
|
||||
गैर-मौजूदा संग्रहों के लिए लेखन सत्यापन
|
||||
गैर-मौजूदा संग्रहों के लिए क्वेरी हैंडलिंग
|
||||
सभी स्टोरों में संग्रह हटाने का क्रम
|
||||
त्रुटि प्रबंधन और पुनर्प्राप्ति परिदृश्य
|
||||
प्रत्येक स्टोरेज बैकएंड के लिए यूनिट परीक्षण
|
||||
क्रॉस-स्टोर संचालन के लिए एकीकरण परीक्षण
|
||||
|
||||
## कार्यान्वयन स्थिति
|
||||
|
||||
### ✅ पूर्ण घटक
|
||||
|
||||
1. **लाइब्रेरियन संग्रह प्रबंधन सेवा** (`trustgraph-flow/trustgraph/librarian/collection_manager.py`)
|
||||
संग्रह मेटाडेटा CRUD संचालन (सूची, अपडेट, हटाएं)
|
||||
`LibraryTableStore` के माध्यम से कैसेंड्रा संग्रह मेटाडेटा तालिका एकीकरण
|
||||
सभी स्टोरेज प्रकारों में संग्रह हटाने का समन्वय
|
||||
उचित त्रुटि प्रबंधन के साथ एसिंक्रोनस अनुरोध/प्रतिक्रिया हैंडलिंग
|
||||
|
||||
2. **संग्रह मेटाडेटा स्कीमा** (`trustgraph-base/trustgraph/schema/services/collection.py`)
|
||||
`CollectionManagementRequest` और `CollectionManagementResponse` स्कीमा
|
||||
संग्रह रिकॉर्ड के लिए `CollectionMetadata` स्कीमा
|
||||
संग्रह अनुरोध/प्रतिक्रिया कतार विषय परिभाषाएँ
|
||||
|
||||
3. **स्टोरेज प्रबंधन स्कीमा** (`trustgraph-base/trustgraph/schema/services/storage.py`)
|
||||
`StorageManagementRequest` और `StorageManagementResponse` स्कीमा
|
||||
स्टोरेज प्रबंधन कतार विषय परिभाषित
|
||||
स्टोरेज-स्तरीय संग्रह संचालन के लिए संदेश प्रारूप
|
||||
|
||||
4. **कैसेंड्रा 4-टेबल स्कीमा** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py`)
|
||||
क्वेरी प्रदर्शन के लिए कंपाउंड पार्टीशन कुंजी
|
||||
SPO प्रश्नों और हटाने ट्रैकिंग के लिए `triples_collection` तालिका
|
||||
संग्रह हटाने को रीड-देन-डिलीट पैटर्न के साथ लागू किया गया
|
||||
|
||||
### ✅ कॉन्फ़िग-आधारित पैटर्न में माइग्रेशन - पूर्ण
|
||||
|
||||
**सभी स्टोरेज बैकएंड को कतार-आधारित पैटर्न से कॉन्फ़िग-आधारित `CollectionConfigHandler` पैटर्न में माइग्रेट किया गया है।**
|
||||
|
||||
माइग्रेशन पूर्ण:
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/neo4j/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/memgraph/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/falkordb/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
|
||||
सभी बैकएंड अब:
|
||||
`CollectionConfigHandler` से विरासत में मिला है
|
||||
`self.register_config_handler(self.on_collection_config)` के माध्यम से कॉन्फ़िग पुश नोटिफिकेशन के लिए पंजीकरण करें
|
||||
`create_collection(user, collection, metadata)` और `delete_collection(user, collection)` को लागू करें
|
||||
लिखने से पहले `collection_exists(user, collection)` का उपयोग करके सत्यापन करें
|
||||
कॉन्फ़िग सेवा परिवर्तनों के साथ स्वचालित रूप से सिंक करें
|
||||
|
||||
विरासत कतार-आधारित बुनियादी ढांचा हटाया गया:
|
||||
✅ `StorageManagementRequest` और `StorageManagementResponse` स्कीमा हटाए गए
|
||||
✅ स्टोरेज प्रबंधन कतार विषय परिभाषाएँ हटाई गईं
|
||||
✅ सभी बैकएंड से स्टोरेज प्रबंधन उपभोक्ता/उत्पादक हटाए गए
|
||||
✅ सभी बैकएंड से `on_storage_management` हैंडलर हटाए गए
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Collection Management Technical Specification"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Collection Management Technical Specification
|
||||
|
||||
## Overview
|
||||
|
|
@ -400,4 +406,3 @@ Legacy queue-based infrastructure removed:
|
|||
- ✅ Removed storage management queue topic definitions
|
||||
- ✅ Removed storage management consumer/producer from all backends
|
||||
- ✅ Removed `on_storage_management` handlers from all backends
|
||||
|
||||
|
|
|
|||
410
docs/tech-specs/collection-management.pt.md
Normal file
410
docs/tech-specs/collection-management.pt.md
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificação Técnica de Gerenciamento de Coleções"
|
||||
parent: "Portuguese (Beta)"
|
||||
---
|
||||
|
||||
# Especificação Técnica de Gerenciamento de Coleções
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Esta especificação descreve as capacidades de gerenciamento de coleções para o TrustGraph, exigindo a criação explícita de coleções e fornecendo controle direto sobre o ciclo de vida da coleção. As coleções devem ser criadas explicitamente antes de serem usadas, garantindo a sincronização adequada entre os metadados do bibliotecário e todos os backends de armazenamento. O recurso suporta quatro casos de uso primários:
|
||||
|
||||
1. **Criação de Coleção**: Crie explicitamente coleções antes de armazenar dados
|
||||
2. **Listagem de Coleções**: Visualize todas as coleções existentes no sistema
|
||||
3. **Gerenciamento de Metadados da Coleção**: Atualize nomes, descrições e tags de coleções
|
||||
4. **Exclusão de Coleções**: Remova coleções e seus dados associados em todos os tipos de armazenamento
|
||||
|
||||
## Objetivos
|
||||
|
||||
**Criação Explícita de Coleção**: Exigir que as coleções sejam criadas antes que os dados possam ser armazenados
|
||||
**Sincronização de Armazenamento**: Garantir que as coleções existam em todos os backends de armazenamento (vetores, objetos, triplas)
|
||||
**Visibilidade da Coleção**: Permitir que os usuários listem e inspecionem todas as coleções em seu ambiente
|
||||
**Limpeza de Coleções**: Permitir a exclusão de coleções que não são mais necessárias
|
||||
**Organização de Coleções**: Suportar rótulos e tags para melhor rastreamento e descoberta de coleções
|
||||
**Gerenciamento de Metadados**: Associar metadados significativos às coleções para clareza operacional
|
||||
**Descoberta de Coleções**: Facilitar a localização de coleções específicas por meio de filtragem e pesquisa
|
||||
**Transparência Operacional**: Fornecer visibilidade clara do ciclo de vida e do uso da coleção
|
||||
**Gerenciamento de Recursos**: Permitir a limpeza de coleções não utilizadas para otimizar a utilização de recursos
|
||||
**Integridade de Dados**: Impedir a criação de coleções órfãs no armazenamento sem rastreamento de metadados
|
||||
|
||||
## Contexto
|
||||
|
||||
Anteriormente, as coleções no TrustGraph eram criadas implicitamente durante as operações de carregamento de dados, levando a problemas de sincronização em que as coleções poderiam existir em backends de armazenamento sem metadados correspondentes no bibliotecário. Isso criava desafios de gerenciamento e dados órfãos.
|
||||
|
||||
O modelo de criação explícita de coleções aborda esses problemas:
|
||||
Exigindo que as coleções sejam criadas antes de serem usadas via `tg-set-collection`
|
||||
Transmitindo a criação da coleção para todos os backends de armazenamento
|
||||
Mantendo um estado sincronizado entre os metadados do bibliotecário e o armazenamento
|
||||
Impedindo a gravação em coleções inexistentes
|
||||
Fornecendo gerenciamento claro do ciclo de vida da coleção
|
||||
|
||||
Esta especificação define o modelo de gerenciamento explícito de coleções. Ao exigir a criação explícita de coleções, o TrustGraph garante:
|
||||
Que as coleções sejam rastreadas nos metadados do bibliotecário desde a criação
|
||||
Que todos os backends de armazenamento estejam cientes das coleções antes de receber dados
|
||||
Que não existam coleções órfãs no armazenamento
|
||||
Visibilidade e controle operacionais claros sobre o ciclo de vida da coleção
|
||||
Tratamento de erros consistente quando as operações referenciam coleções inexistentes
|
||||
|
||||
## Design Técnico
|
||||
|
||||
### Arquitetura
|
||||
|
||||
O sistema de gerenciamento de coleções será implementado dentro da infraestrutura existente do TrustGraph:
|
||||
|
||||
1. **Integração do Serviço do Bibliotecário**
|
||||
As operações de gerenciamento de coleções serão adicionadas ao serviço do bibliotecário existente
|
||||
Nenhum novo serviço é necessário - aproveita os padrões de autenticação e acesso existentes
|
||||
Lida com a listagem, exclusão e gerenciamento de metadados de coleções
|
||||
|
||||
Módulo: trustgraph-librarian
|
||||
|
||||
2. **Tabela de Metadados de Coleção do Cassandra**
|
||||
Nova tabela no keyspace existente do bibliotecário
|
||||
Armazena metadados da coleção com acesso específico ao usuário
|
||||
Chave primária: (user_id, collection_id) para multilocação adequada
|
||||
|
||||
Módulo: trustgraph-librarian
|
||||
|
||||
3. **CLI de Gerenciamento de Coleções**
|
||||
Interface de linha de comando para operações de coleção
|
||||
Fornece comandos de listagem, exclusão, rotulagem e gerenciamento de tags
|
||||
Integra-se com o framework de CLI existente
|
||||
|
||||
Módulo: trustgraph-cli
|
||||
|
||||
### Modelos de Dados
|
||||
|
||||
#### Tabela de Metadados de Coleção do Cassandra
|
||||
|
||||
Os metadados da coleção serão armazenados em uma tabela estruturada do Cassandra no keyspace do bibliotecário:
|
||||
|
||||
```sql
|
||||
CREATE TABLE collections (
|
||||
user text,
|
||||
collection text,
|
||||
name text,
|
||||
description text,
|
||||
tags set<text>,
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
PRIMARY KEY (user, collection)
|
||||
);
|
||||
```
|
||||
|
||||
Estrutura da tabela:
|
||||
**user** + **collection**: Chave primária composta que garante o isolamento do usuário
|
||||
**name**: Nome da coleção legível por humanos
|
||||
**description**: Descrição detalhada do propósito da coleção
|
||||
**tags**: Conjunto de tags para categorização e filtragem
|
||||
**created_at**: Timestamp de criação da coleção
|
||||
**updated_at**: Timestamp da última modificação
|
||||
|
||||
Esta abordagem permite:
|
||||
Gerenciamento de coleções multi-tenant com isolamento de usuário
|
||||
Consulta eficiente por usuário e coleção
|
||||
Sistema de tags flexível para organização
|
||||
Rastreamento do ciclo de vida para insights operacionais
|
||||
|
||||
#### Ciclo de Vida da Coleção
|
||||
|
||||
As coleções são explicitamente criadas no gerenciador antes que as operações de dados possam prosseguir:
|
||||
|
||||
1. **Criação da Coleção** (Dois Caminhos):
|
||||
|
||||
**Caminho A: Criação Iniciada pelo Usuário** via `tg-set-collection`:
|
||||
O usuário fornece o ID da coleção, nome, descrição e tags
|
||||
O gerenciador cria um registro de metadados na tabela `collections`
|
||||
O gerenciador transmite "create-collection" para todos os backends de armazenamento
|
||||
Todos os processadores de armazenamento criam a coleção e confirmam o sucesso
|
||||
A coleção está agora pronta para operações de dados
|
||||
|
||||
**Caminho B: Criação Automática na Submissão de Documento**:
|
||||
O usuário submete um documento especificando um ID de coleção
|
||||
O gerenciador verifica se a coleção existe na tabela de metadados
|
||||
Se não existir: O gerenciador cria metadados com valores padrão (nome=collection_id, descrição/tags vazias)
|
||||
O gerenciador transmite "create-collection" para todos os backends de armazenamento
|
||||
Todos os processadores de armazenamento criam a coleção e confirmam o sucesso
|
||||
O processamento do documento prossegue com a coleção agora estabelecida
|
||||
|
||||
Ambos os caminhos garantem que a coleção exista nos metadados do gerenciador E em todos os backends de armazenamento antes de permitir operações de dados.
|
||||
|
||||
2. **Validação de Armazenamento**: As operações de escrita validam se a coleção existe:
|
||||
Os processadores de armazenamento verificam o estado da coleção antes de aceitar escritas
|
||||
As escritas em coleções inexistentes retornam um erro
|
||||
Isso impede que as escritas contornem a lógica de criação de coleção do gerenciador
|
||||
|
||||
3. **Comportamento da Consulta**: As operações de consulta lidam com coleções inexistentes de forma elegante:
|
||||
As consultas em coleções inexistentes retornam resultados vazios
|
||||
Nenhum erro é lançado para operações de consulta
|
||||
Permite a exploração sem exigir que a coleção exista
|
||||
|
||||
4. **Atualizações de Metadados**: Os usuários podem atualizar os metadados da coleção após a criação:
|
||||
Atualize o nome, a descrição e as tags via `tg-set-collection`
|
||||
As atualizações se aplicam apenas aos metadados do gerenciador
|
||||
Os backends de armazenamento mantêm a coleção, mas as atualizações de metadados não são propagadas
|
||||
|
||||
5. **Exclusão Explícita**: Os usuários excluem coleções via `tg-delete-collection`:
|
||||
O gerenciador transmite "delete-collection" para todos os backends de armazenamento
|
||||
Aguarda a confirmação de todos os processadores de armazenamento
|
||||
Exclui o registro de metadados do gerenciador somente após a limpeza do armazenamento estar completa
|
||||
Garante que nenhum dado órfão permaneça no armazenamento
|
||||
|
||||
**Princípio Chave**: O gerenciador é o ponto de controle único para a criação de coleções. Seja iniciada por um comando do usuário ou pela submissão de um documento, o gerenciador garante o rastreamento adequado de metadados e a sincronização do backend de armazenamento antes de permitir operações de dados.
|
||||
|
||||
Operações necessárias:
|
||||
**Criar Coleção**: Operação do usuário via `tg-set-collection` OU automática na submissão de documento
|
||||
**Atualizar Metadados da Coleção**: Operação do usuário para modificar o nome, a descrição e as tags
|
||||
**Excluir Coleção**: Operação do usuário para remover a coleção e seus dados em todos os armazenamentos
|
||||
**Listar Coleções**: Operação do usuário para visualizar coleções com filtragem por tags
|
||||
|
||||
#### Gerenciamento de Coleções em Múltiplos Armazenamentos
|
||||
|
||||
As coleções existem em vários backends de armazenamento no TrustGraph:
|
||||
**Vector Stores** (Qdrant, Milvus, Pinecone): Armazena embeddings e dados vetoriais
|
||||
**Object Stores** (Cassandra): Armazena documentos e dados de arquivos
|
||||
**Triple Stores** (Cassandra, Neo4j, Memgraph, FalkorDB): Armazena dados de grafo/RDF
|
||||
|
||||
Cada tipo de armazenamento implementa:
|
||||
**Rastreamento do Estado da Coleção**: Manter o conhecimento de quais coleções existem
|
||||
**Criação de Coleção**: Aceitar e processar operações de "criar-coleção"
|
||||
**Validação de Coleção**: Verificar se a coleção existe antes de aceitar gravações
|
||||
**Exclusão de Coleção**: Remover todos os dados para a coleção especificada
|
||||
|
||||
O serviço de bibliotecário coordena as operações de coleção em todos os tipos de armazenamento, garantindo:
|
||||
Que as coleções sejam criadas em todos os backends antes de serem usadas
|
||||
Que todos os backends confirmem a criação antes de retornar o sucesso
|
||||
Ciclo de vida da coleção sincronizado em todos os tipos de armazenamento
|
||||
Tratamento de erros consistente quando as coleções não existem
|
||||
|
||||
#### Rastreamento do Estado da Coleção por Tipo de Armazenamento
|
||||
|
||||
Cada backend de armazenamento rastreia o estado da coleção de forma diferente, com base em suas capacidades:
|
||||
|
||||
**Cassandra Triple Store:**
|
||||
Usa a tabela `triples_collection` existente
|
||||
Cria um triple de marcador do sistema quando a coleção é criada
|
||||
Consulta: `SELECT collection FROM triples_collection WHERE collection = ? LIMIT 1`
|
||||
Verificação de existência de coleção eficiente de partição única
|
||||
|
||||
**Qdrant/Milvus/Pinecone Vector Stores:**
|
||||
As APIs nativas de coleção fornecem verificação de existência
|
||||
Coleções criadas com configuração de vetor adequada
|
||||
O método `collection_exists()` usa a API de armazenamento
|
||||
A criação da coleção valida os requisitos de dimensão
|
||||
|
||||
**Neo4j/Memgraph/FalkorDB Graph Stores:**
|
||||
Usa nós `:CollectionMetadata` para rastrear coleções
|
||||
Propriedades do nó: `{user, collection, created_at}`
|
||||
Consulta: `MATCH (c:CollectionMetadata {user: $user, collection: $collection})`
|
||||
Separado de nós de dados para uma separação limpa
|
||||
Permite listagem e validação eficientes de coleções
|
||||
|
||||
**Cassandra Object Store:**
|
||||
Usa a tabela de metadados da coleção ou linhas de marcador
|
||||
Padrão semelhante ao triple store
|
||||
Valida a coleção antes das gravações de documentos
|
||||
|
||||
### APIs
|
||||
|
||||
APIs de Gerenciamento de Coleção (Bibliotecário):
|
||||
**Criar/Atualizar Coleção**: Criar uma nova coleção ou atualizar metadados existentes via `tg-set-collection`
|
||||
**Listar Coleções**: Recuperar coleções para um usuário com filtragem opcional por tag
|
||||
**Excluir Coleção**: Remover a coleção e os dados associados, propagando para todos os tipos de armazenamento
|
||||
|
||||
APIs de Gerenciamento de Armazenamento (Todos os Processadores de Armazenamento):
|
||||
**Criar Coleção**: Lidar com a operação de "criar-coleção", estabelecer a coleção no armazenamento
|
||||
**Excluir Coleção**: Lidar com a operação de "excluir-coleção", remover todos os dados da coleção
|
||||
**Verificação de Existência da Coleção**: Validação interna antes de aceitar operações de gravação
|
||||
|
||||
APIs de Operação de Dados (Comportamento Modificado):
|
||||
**APIs de Gravação**: Validar se a coleção existe antes de aceitar dados, retornar um erro se não existir
|
||||
**APIs de Consulta**: Retornar resultados vazios para coleções inexistentes sem erro
|
||||
|
||||
### Detalhes de Implementação
|
||||
|
||||
A implementação seguirá os padrões existentes do TrustGraph para integração de serviços e estrutura de comandos de linha de comando.
|
||||
|
||||
#### Exclusão em Cadeia de Coleção
|
||||
|
||||
Quando um usuário inicia a exclusão de uma coleção por meio do serviço de bibliotecário:
|
||||
|
||||
1. **Validação de Metadados**: Verificar se a coleção existe e se o usuário tem permissão para excluí-la
|
||||
2. **Propagação para o Armazenamento**: O bibliotecário coordena a exclusão em todos os escritores de armazenamento:
|
||||
Escritor de armazenamento vetorial: Remover incorporações e índices de vetor para o usuário e a coleção
|
||||
Escritor de armazenamento de objetos: Remover documentos e arquivos para o usuário e a coleção
|
||||
Escritor de triple store: Remover dados de grafo e triples para o usuário e a coleção
|
||||
3. **Limpeza de Metadados**: Remover o registro de metadados da coleção do Cassandra
|
||||
4. **Tratamento de Erros**: Se alguma exclusão de armazenamento falhar, manter a consistência por meio de mecanismos de reversão ou repetição
|
||||
|
||||
#### Interface de Gerenciamento de Coleção
|
||||
|
||||
**⚠️ ABORDAGEM ANTIGA - SUBSTITUÍDA POR PADRÃO BASEADO EM CONFIGURAÇÃO**
|
||||
|
||||
A arquitetura baseada em fila descrita abaixo foi substituída por uma abordagem baseada em configuração usando `CollectionConfigHandler`. Todos os backends de armazenamento agora recebem atualizações de coleção por meio de mensagens de configuração em vez de filas de gerenciamento dedicadas.
|
||||
|
||||
~~Todos os escritores de armazenamento implementam uma interface de gerenciamento de coleção padronizada com um esquema comum:~~
|
||||
|
||||
~~**Esquema de Mensagem (`StorageManagementRequest`):**~~
|
||||
```json
|
||||
{
|
||||
"operation": "create-collection" | "delete-collection",
|
||||
"user": "user123",
|
||||
"collection": "documents-2024"
|
||||
}
|
||||
```
|
||||
|
||||
~~**Arquitetura de Filas:**~~
|
||||
~~**Fila de Gerenciamento de Vetores** (`vector-storage-management`): Armazenamentos de vetores/embeddings~~
|
||||
~~**Fila de Gerenciamento de Objetos** (`object-storage-management`): Armazenamentos de objetos/documentos~~
|
||||
~~**Fila de Gerenciamento de Triplas** (`triples-storage-management`): Armazenamentos de grafos/RDF~~
|
||||
~~**Fila de Resposta de Armazenamento** (`storage-management-response`): Todas as respostas são enviadas aqui~~
|
||||
|
||||
**Implementação Atual:**
|
||||
|
||||
Todos os backends de armazenamento agora usam `CollectionConfigHandler`:
|
||||
**Integração de Configuração Push**: Os serviços de armazenamento se registram para notificações de configuração push
|
||||
**Sincronização Automática**: Coleções criadas/excluídas com base em alterações de configuração
|
||||
**Modelo Declarativo**: Coleções definidas no serviço de configuração, os backends sincronizam para corresponder
|
||||
**Sem Requisição/Resposta**: Elimina a sobrecarga de coordenação e o rastreamento de respostas
|
||||
**Rastreamento do Estado da Coleção**: Mantido via cache `known_collections`
|
||||
**Operações Idempotentes**: É seguro processar a mesma configuração várias vezes
|
||||
|
||||
Cada backend de armazenamento implementa:
|
||||
`create_collection(user: str, collection: str, metadata: dict)` - Criar estruturas de coleção
|
||||
`delete_collection(user: str, collection: str)` - Remover todos os dados da coleção
|
||||
`collection_exists(user: str, collection: str) -> bool` - Validar antes de gravar
|
||||
|
||||
#### Refatoração do Armazenamento de Triplas Cassandra
|
||||
|
||||
Como parte desta implementação, o armazenamento de triplas Cassandra será refatorado de um modelo de tabela por coleção para um modelo de tabela unificada:
|
||||
|
||||
**Arquitetura Atual:**
|
||||
Keyspace por usuário, tabela separada por coleção
|
||||
Esquema: `(s, p, o)` com `PRIMARY KEY (s, p, o)`
|
||||
Nomes de tabela: coleções de usuários se tornam tabelas Cassandra separadas
|
||||
|
||||
**Nova Arquitetura:**
|
||||
Keyspace por usuário, tabela única "triples" para todas as coleções
|
||||
Esquema: `(collection, s, p, o)` com `PRIMARY KEY (collection, s, p, o)`
|
||||
Isolamento de coleção por meio de particionamento de coleção
|
||||
|
||||
**Alterações Necessárias:**
|
||||
|
||||
1. **Refatoração da Classe TrustGraph** (`trustgraph/direct/cassandra.py`):
|
||||
Remover o parâmetro `table` do construtor, usar a tabela "triples" fixa
|
||||
Adicionar o parâmetro `collection` a todos os métodos
|
||||
Atualizar o esquema para incluir a coleção como a primeira coluna
|
||||
**Atualizações de Índice**: Novos índices serão criados para suportar todos os 8 padrões de consulta:
|
||||
Índice em `(s)` para consultas baseadas em sujeito
|
||||
Índice em `(p)` para consultas baseadas em predicado
|
||||
Índice em `(o)` para consultas baseadas em objeto
|
||||
Observação: O Cassandra não suporta índices secundários multi-coluna, portanto, estes são índices de coluna única
|
||||
|
||||
**Desempenho do Padrão de Consulta:**
|
||||
✅ `get_all()` - varredura de partição em `collection`
|
||||
✅ `get_s(s)` - usa a chave primária de forma eficiente (`collection, s`)
|
||||
✅ `get_p(p)` - usa `idx_p` com filtragem `collection`
|
||||
✅ `get_o(o)` - usa `idx_o` com filtragem `collection`
|
||||
✅ `get_sp(s, p)` - usa a chave primária de forma eficiente (`collection, s, p`)
|
||||
⚠️ `get_po(p, o)` - requer `ALLOW FILTERING` (usa `idx_p` ou `idx_o` mais filtragem)
|
||||
✅ `get_os(o, s)` - usa `idx_o` com filtragem adicional em `s`
|
||||
✅ `get_spo(s, p, o)` - usa toda a chave primária de forma eficiente
|
||||
|
||||
**Observação sobre ALLOW FILTERING**: O padrão de consulta `get_po` requer `ALLOW FILTERING`, pois precisa tanto de restrições de predicado quanto de objeto sem um índice composto adequado. Isso é aceitável, pois este padrão de consulta é menos comum do que as consultas baseadas em sujeito no uso típico de armazenamentos de triplas.
|
||||
|
||||
2. **Atualizações do Gravador de Armazenamento** (`trustgraph/storage/triples/cassandra/write.py`):
|
||||
Manter uma única conexão TrustGraph por usuário em vez de por (usuário, coleção)
|
||||
Passar a coleção para as operações de inserção
|
||||
Melhor utilização de recursos com menos conexões
|
||||
|
||||
3. **Atualizações do Serviço de Consulta** (`trustgraph/query/triples/cassandra/service.py`):
|
||||
Uma única conexão TrustGraph por usuário
|
||||
Passar a coleção para todas as operações de consulta
|
||||
Manter a mesma lógica de consulta com o parâmetro de coleção
|
||||
|
||||
**Benefícios:**
|
||||
**Exclusão Simplificada de Coleções**: Excluir usando a chave de partição `collection` em todas as 4 tabelas
|
||||
**Eficiência de Recursos**: Menos conexões de banco de dados e objetos de tabela
|
||||
**Operações entre Coleções**: Mais fácil de implementar operações que abrangem várias coleções
|
||||
**Arquitetura Consistente**: Alinha-se com a abordagem unificada de metadados de coleção
|
||||
**Validação de Coleção**: Fácil de verificar a existência da coleção via tabela `triples_collection`
|
||||
|
||||
As operações de coleção serão atômicas sempre que possível e fornecerão tratamento de erros e validação apropriados.
|
||||
|
||||
## Considerações de Segurança
|
||||
|
||||
As operações de gerenciamento de coleção requerem autorização apropriada para evitar acesso ou exclusão não autorizados de coleções. O controle de acesso estará alinhado com os modelos de segurança TrustGraph existentes.
|
||||
|
||||
## Considerações de Desempenho
|
||||
|
||||
As operações de listagem de coleções podem precisar de paginação para ambientes com um grande número de coleções. As consultas de metadados devem ser otimizadas para padrões de filtragem comuns.
|
||||
|
||||
## Estratégia de Testes
|
||||
|
||||
Os testes abrangentes cobrirão:
|
||||
Fluxo de trabalho de criação de coleção de ponta a ponta
|
||||
Sincronização do armazenamento de back-end
|
||||
Validação de gravação para coleções inexistentes
|
||||
Tratamento de consultas para coleções inexistentes
|
||||
Exclusão de coleção em cascata em todos os armazenamentos
|
||||
Cenários de tratamento de erros e recuperação
|
||||
Testes unitários para cada armazenamento de back-end
|
||||
Testes de integração para operações entre armazenamentos
|
||||
|
||||
## Status da Implementação
|
||||
|
||||
### ✅ Componentes Concluídos
|
||||
|
||||
1. **Serviço de Gerenciamento de Coleção Librarian** (`trustgraph-flow/trustgraph/librarian/collection_manager.py`)
|
||||
Operações CRUD de metadados de coleção (listagem, atualização, exclusão)
|
||||
Integração da tabela de metadados de coleção do Cassandra via `LibraryTableStore`
|
||||
Coordenação da exclusão de coleção em cascata em todos os tipos de armazenamento
|
||||
Tratamento de solicitações/respostas assíncronas com gerenciamento de erros adequado
|
||||
|
||||
2. **Esquema de Metadados de Coleção** (`trustgraph-base/trustgraph/schema/services/collection.py`)
|
||||
Esquemas `CollectionManagementRequest` e `CollectionManagementResponse`
|
||||
Esquema `CollectionMetadata` para registros de coleção
|
||||
Definições de tópicos de fila de solicitações/respostas de coleção
|
||||
|
||||
3. **Esquema de Gerenciamento de Armazenamento** (`trustgraph-base/trustgraph/schema/services/storage.py`)
|
||||
Esquemas `StorageManagementRequest` e `StorageManagementResponse`
|
||||
Tópicos de fila de gerenciamento de armazenamento definidos
|
||||
Formato de mensagem para operações de coleção no nível do armazenamento
|
||||
|
||||
4. **Esquema de 4 Tabelas do Cassandra** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py`)
|
||||
Chaves de partição compostas para desempenho da consulta
|
||||
Tabela `triples_collection` para consultas SPO e rastreamento de exclusão
|
||||
Exclusão de coleção implementada com o padrão de leitura e exclusão
|
||||
|
||||
### ✅ Migração para Padrão Baseado em Configuração - CONCLUÍDO
|
||||
|
||||
**Todos os armazenamentos de back-end foram migrados do padrão baseado em fila para o padrão baseado em configuração `CollectionConfigHandler`.**
|
||||
|
||||
Migrações concluídas:
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/neo4j/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/memgraph/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/falkordb/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
|
||||
Todos os backends agora:
|
||||
Herdam de `CollectionConfigHandler`
|
||||
Registram-se para notificações de push de configuração via `self.register_config_handler(self.on_collection_config)`
|
||||
Implementam `create_collection(user, collection, metadata)` e `delete_collection(user, collection)`
|
||||
Usam `collection_exists(user, collection)` para validar antes de gravar
|
||||
Sincronizam automaticamente com as alterações do serviço de configuração
|
||||
|
||||
Infraestrutura baseada em fila herdada removida:
|
||||
✅ Esquemas `StorageManagementRequest` e `StorageManagementResponse` removidos
|
||||
✅ Definições de tópicos de fila de gerenciamento de armazenamento removidas
|
||||
✅ Consumidor/produtor de gerenciamento de armazenamento removido de todos os backends
|
||||
✅ Manipuladores `on_storage_management` removidos de todos os backends
|
||||
410
docs/tech-specs/collection-management.ru.md
Normal file
410
docs/tech-specs/collection-management.ru.md
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Техническая спецификация управления коллекциями"
|
||||
parent: "Russian (Beta)"
|
||||
---
|
||||
|
||||
# Техническая спецификация управления коллекциями
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Обзор
|
||||
|
||||
Эта спецификация описывает возможности управления коллекциями для TrustGraph, требуя явного создания коллекций и обеспечивая прямой контроль над жизненным циклом коллекций. Коллекции должны быть явно созданы перед использованием, что обеспечивает надлежащую синхронизацию между метаданными библиотекаря и всеми хранилищами. Эта функция поддерживает четыре основных сценария использования:
|
||||
|
||||
1. **Создание коллекции**: Явно создавайте коллекции перед сохранением данных.
|
||||
2. **Перечисление коллекций**: Просматривайте все существующие коллекции в системе.
|
||||
3. **Управление метаданными коллекции**: Обновляйте имена, описания и теги коллекций.
|
||||
4. **Удаление коллекции**: Удаляйте коллекции и связанные с ними данные во всех типах хранилищ.
|
||||
|
||||
## Цели
|
||||
|
||||
**Явное создание коллекции**: Требуйте, чтобы коллекции создавались перед сохранением данных.
|
||||
**Синхронизация хранилищ**: Обеспечьте наличие коллекций во всех хранилищах (векторах, объектах, тройках).
|
||||
**Видимость коллекций**: Предоставьте пользователям возможность перечислять и просматривать все коллекции в их среде.
|
||||
**Очистка коллекций**: Разрешите удаление коллекций, которые больше не нужны.
|
||||
**Организация коллекций**: Поддержка меток и тегов для лучшего отслеживания и обнаружения коллекций.
|
||||
**Управление метаданными**: Связывайте значимые метаданные с коллекциями для обеспечения оперативной ясности.
|
||||
**Обнаружение коллекций**: Облегчите поиск конкретных коллекций с помощью фильтрации и поиска.
|
||||
**Оперативная прозрачность**: Обеспечьте четкую видимость жизненного цикла и использования коллекций.
|
||||
**Управление ресурсами**: Позвольте очищать неиспользуемые коллекции для оптимизации использования ресурсов.
|
||||
**Целостность данных**: Предотвратите появление "сиротских" коллекций в хранилище без отслеживания метаданных.
|
||||
|
||||
## Предыстория
|
||||
|
||||
Ранее коллекции в TrustGraph создавались неявно во время операций загрузки данных, что приводило к проблемам синхронизации, когда коллекции могли существовать в хранилищах без соответствующих метаданных в библиотекаре. Это создавало проблемы управления и потенциальные "сиротские" данные.
|
||||
|
||||
Модель явного создания коллекций решает эти проблемы следующим образом:
|
||||
Требует создания коллекций перед использованием через `tg-set-collection`.
|
||||
Передает информацию о создании коллекции во все хранилища.
|
||||
Поддерживает синхронизированное состояние между метаданными библиотекаря и хранилищем.
|
||||
Предотвращает запись в несуществующие коллекции.
|
||||
Обеспечивает четкое управление жизненным циклом коллекций.
|
||||
|
||||
Эта спецификация определяет модель явного управления коллекциями. Требуя явного создания коллекций, TrustGraph обеспечивает:
|
||||
Отслеживание коллекций в метаданных библиотекаря с момента создания.
|
||||
Знание всеми хранилищами о коллекциях до получения данных.
|
||||
Отсутствие "сиротских" коллекций в хранилище.
|
||||
Четкую оперативную видимость и контроль над жизненным циклом коллекций.
|
||||
Последовательную обработку ошибок при выполнении операций, ссылающихся на несуществующие коллекции.
|
||||
|
||||
## Технический дизайн
|
||||
|
||||
### Архитектура
|
||||
|
||||
Система управления коллекциями будет реализована в существующей инфраструктуре TrustGraph:
|
||||
|
||||
1. **Интеграция с сервисом библиотекаря**
|
||||
Операции управления коллекциями будут добавлены в существующий сервис библиотекаря.
|
||||
Не требуется новый сервис - используется существующая аутентификация и модели доступа.
|
||||
Обрабатывает перечисление коллекций, удаление и управление метаданными.
|
||||
|
||||
Модуль: trustgraph-librarian
|
||||
|
||||
2. **Таблица метаданных коллекций Cassandra**
|
||||
Новая таблица в существующем пространстве ключей библиотекаря.
|
||||
Хранит метаданные коллекций с доступом, специфичным для пользователя.
|
||||
Первичный ключ: (user_id, collection_id) для обеспечения правильной многопользовательской среды.
|
||||
|
||||
Модуль: trustgraph-librarian
|
||||
|
||||
3. **CLI для управления коллекциями**
|
||||
Интерфейс командной строки для операций с коллекциями.
|
||||
Предоставляет команды для перечисления, удаления, добавления меток и тегов.
|
||||
Интегрируется с существующей инфраструктурой CLI.
|
||||
|
||||
Модуль: trustgraph-cli
|
||||
|
||||
### Модели данных
|
||||
|
||||
#### Таблица метаданных коллекций Cassandra
|
||||
|
||||
Метаданные коллекций будут храниться в структурированной таблице Cassandra в пространстве ключей библиотекаря:
|
||||
|
||||
```sql
|
||||
CREATE TABLE collections (
|
||||
user text,
|
||||
collection text,
|
||||
name text,
|
||||
description text,
|
||||
tags set<text>,
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
PRIMARY KEY (user, collection)
|
||||
);
|
||||
```
|
||||
|
||||
Структура таблицы:
|
||||
**user** + **collection**: Составной первичный ключ, обеспечивающий изоляцию пользователей
|
||||
**name**: Человекочитаемое имя коллекции
|
||||
**description**: Подробное описание назначения коллекции
|
||||
**tags**: Набор тегов для категоризации и фильтрации
|
||||
**created_at**: Временная метка создания коллекции
|
||||
**updated_at**: Временная метка последнего изменения
|
||||
|
||||
Этот подход позволяет:
|
||||
Управление коллекциями с поддержкой многопользовательского режима и изоляцией пользователей
|
||||
Эффективный поиск по пользователю и коллекции
|
||||
Гибкая система тегирования для организации
|
||||
Отслеживание жизненного цикла для получения оперативной информации
|
||||
|
||||
#### Жизненный цикл коллекции
|
||||
|
||||
Коллекции явно создаются в библиотечнике, прежде чем можно будет выполнять операции с данными:
|
||||
|
||||
1. **Создание коллекции** (Два пути):
|
||||
|
||||
**Путь A: Создание, инициированное пользователем** через `tg-set-collection`:
|
||||
Пользователь предоставляет идентификатор коллекции, имя, описание и теги
|
||||
Библиотечник создает запись метаданных в таблице `collections`
|
||||
Библиотечник отправляет сообщение "create-collection" всем хранилищам данных
|
||||
Все процессоры хранилищ создают коллекцию и подтверждают успешное выполнение
|
||||
Коллекция готова для операций с данными
|
||||
|
||||
**Путь B: Автоматическое создание при отправке документа**:
|
||||
Пользователь отправляет документ, указывающий идентификатор коллекции
|
||||
Библиотечник проверяет, существует ли коллекция в таблице метаданных
|
||||
Если коллекция не существует: Библиотечник создает метаданные с настройками по умолчанию (имя = идентификатор коллекции, пустое описание/теги)
|
||||
Библиотечник отправляет сообщение "create-collection" всем хранилищам данных
|
||||
Все процессоры хранилищ создают коллекцию и подтверждают успешное выполнение
|
||||
Обработка документа продолжается после создания коллекции
|
||||
|
||||
Оба пути обеспечивают существование коллекции в метаданных библиотечника И во всех хранилищах данных перед выполнением операций с данными.
|
||||
|
||||
2. **Проверка хранилища**: Операции записи проверяют существование коллекции:
|
||||
Процессоры хранилищ проверяют состояние коллекции перед принятием записи
|
||||
Записи в несуществующие коллекции возвращают ошибку
|
||||
Это предотвращает прямые записи, обходя логику создания коллекции библиотечником
|
||||
|
||||
3. **Поведение при запросах**: Операции запроса корректно обрабатывают несуществующие коллекции:
|
||||
Запросы к несуществующим коллекциям возвращают пустые результаты
|
||||
Не возникает ошибок для операций запроса
|
||||
Позволяет исследовать данные без необходимости существования коллекции
|
||||
|
||||
4. **Обновление метаданных**: Пользователи могут обновлять метаданные коллекции после ее создания:
|
||||
Обновление имени, описания и тегов через `tg-set-collection`
|
||||
Обновления применяются только к метаданным библиотечника
|
||||
Хранилища данных сохраняют коллекцию, но обновления метаданных не распространяются
|
||||
|
||||
5. **Явное удаление**: Пользователи удаляют коллекции через `tg-delete-collection`:
|
||||
Библиотечник отправляет сообщение "delete-collection" всем хранилищам данных
|
||||
Ожидает подтверждение от всех процессоров хранилищ
|
||||
Удаляет запись метаданных библиотечника только после завершения очистки хранилища
|
||||
Обеспечивает отсутствие "осиротевших" данных в хранилище
|
||||
|
||||
**Ключевой принцип**: Библиотечник является центральной точкой управления созданием коллекций. Независимо от того, инициировано ли это пользовательской командой или отправкой документа, библиотечник обеспечивает правильное отслеживание метаданных и синхронизацию хранилищ данных, прежде чем разрешить операции с данными.
|
||||
|
||||
Требуемые операции:
|
||||
**Создание коллекции**: Операция пользователя через `tg-set-collection` ИЛИ автоматическое создание при отправке документа
|
||||
**Обновление метаданных коллекции**: Операция пользователя для изменения имени, описания и тегов
|
||||
**Удаление коллекции**: Операция пользователя для удаления коллекции и ее данных во всех хранилищах
|
||||
**Список коллекций**: Операция пользователя для просмотра коллекций с фильтрацией по тегам
|
||||
|
||||
#### Управление коллекциями в нескольких хранилищах
|
||||
|
||||
Коллекции существуют в нескольких хранилищах данных в TrustGraph:
|
||||
**Векторные хранилища** (Qdrant, Milvus, Pinecone): Хранят вложения и векторные данные
|
||||
**Объектные хранилища** (Cassandra): Хранят документы и файлы
|
||||
**Графовые хранилища** (Cassandra, Neo4j, Memgraph, FalkorDB): Хранят данные графов/RDF
|
||||
|
||||
Каждый тип хранилища реализует:
|
||||
**Отслеживание состояния коллекций**: Поддержание информации о том, какие коллекции существуют.
|
||||
**Создание коллекций**: Прием и обработка операций "создать коллекцию".
|
||||
**Проверка существования коллекций**: Проверка существования коллекции перед записью данных.
|
||||
**Удаление коллекций**: Удаление всех данных для указанной коллекции.
|
||||
|
||||
Сервис библиотекаря координирует операции с коллекциями во всех типах хранилищ, обеспечивая:
|
||||
Создание коллекций во всех бэкендах перед использованием.
|
||||
Подтверждение создания всеми бэкендами перед возвратом успеха.
|
||||
Синхронизированный жизненный цикл коллекций во всех типах хранилища.
|
||||
Последовательную обработку ошибок, когда коллекции не существуют.
|
||||
|
||||
#### Отслеживание состояния коллекций по типу хранилища
|
||||
|
||||
Каждый бэкенд хранилища отслеживает состояние коллекций по-разному, в зависимости от его возможностей:
|
||||
|
||||
**Triple Store на базе Cassandra:**
|
||||
Использует существующую таблицу `triples_collection`.
|
||||
Создает системный маркер-трипл при создании коллекции.
|
||||
Запрос: `SELECT collection FROM triples_collection WHERE collection = ? LIMIT 1`.
|
||||
Эффективная проверка существования коллекции в одной партиции.
|
||||
|
||||
**Векторные хранилища Qdrant/Milvus/Pinecone:**
|
||||
Нативные API коллекций обеспечивают проверку существования.
|
||||
Коллекции создаются с правильной конфигурацией векторов.
|
||||
Метод `collection_exists()` использует API хранилища.
|
||||
Создание коллекции проверяет требования к размерности.
|
||||
|
||||
**Графовые хранилища Neo4j/Memgraph/FalkorDB:**
|
||||
Используют узлы `:CollectionMetadata` для отслеживания коллекций.
|
||||
Свойства узла: `{user, collection, created_at}`.
|
||||
Запрос: `MATCH (c:CollectionMetadata {user: $user, collection: $collection})`.
|
||||
Отделены от узлов данных для четкого разделения.
|
||||
Обеспечивает эффективное перечисление и проверку коллекций.
|
||||
|
||||
**Объектное хранилище на базе Cassandra:**
|
||||
Использует таблицу метаданных коллекции или маркерные строки.
|
||||
Аналогичный шаблон, что и для triple store.
|
||||
Проверяет существование коллекции перед записью документов.
|
||||
|
||||
### API
|
||||
|
||||
API управления коллекциями (Библиотекарь):
|
||||
**Создание/Обновление коллекции**: Создание новой коллекции или обновление существующих метаданных через `tg-set-collection`.
|
||||
**Список коллекций**: Получение коллекций для пользователя с необязательной фильтрацией по тегам.
|
||||
**Удаление коллекции**: Удаление коллекции и связанных данных, распространяясь на все типы хранилищ.
|
||||
|
||||
API управления хранилищем (Все процессоры хранилища):
|
||||
**Создание коллекции**: Обработка операции "создать коллекцию", создание коллекции в хранилище.
|
||||
**Удаление коллекции**: Обработка операции "удалить коллекцию", удаление всех данных коллекции.
|
||||
**Проверка существования коллекции**: Внутренняя проверка перед принятием операций записи.
|
||||
|
||||
API операций с данными (Измененное поведение):
|
||||
**API записи**: Проверка существования коллекции перед принятием данных, возврат ошибки, если коллекция не существует.
|
||||
**API запросов**: Возврат пустых результатов для несуществующих коллекций без ошибки.
|
||||
|
||||
### Детали реализации
|
||||
|
||||
Реализация будет следовать существующим шаблонам TrustGraph для интеграции служб и структуры командной строки.
|
||||
|
||||
#### Каскадное удаление коллекций
|
||||
|
||||
Когда пользователь инициирует удаление коллекции через сервис библиотекаря:
|
||||
|
||||
1. **Проверка метаданных**: Проверка существования коллекции и наличие у пользователя разрешения на удаление.
|
||||
2. **Каскадное удаление в хранилищах**: Библиотекарь координирует удаление во всех хранилищах записи:
|
||||
Хранилище векторов: Удаление вложений и индексов векторов для пользователя и коллекции.
|
||||
Объектное хранилище: Удаление документов и файлов для пользователя и коллекции.
|
||||
Графовое хранилище: Удаление данных графа и триплетов для пользователя и коллекции.
|
||||
3. **Очистка метаданных**: Удаление записи метаданных коллекции из Cassandra.
|
||||
4. **Обработка ошибок**: Если удаление в каком-либо хранилище не удалось, поддерживайте согласованность с помощью механизмов отката или повторной попытки.
|
||||
|
||||
#### Интерфейс управления коллекциями
|
||||
|
||||
**⚠️ УСТАРЕВШИЙ ПОДХОД - ЗАМЕЩЕН ШАБЛОНОМ НА ОСНОВЕ КОНФИГУРАЦИИ**
|
||||
|
||||
Архитектура на основе очереди, описанная ниже, была заменена подходом на основе конфигурации с использованием `CollectionConfigHandler`. Все бэкенды хранилищ теперь получают обновления коллекций через сообщения push конфигурации, а не через выделенные очереди управления.
|
||||
|
||||
~~Все хранилища записи реализуют стандартизированный интерфейс управления коллекциями с общей схемой:~~
|
||||
|
||||
~~**Схема сообщения (`StorageManagementRequest`):**~~
|
||||
```json
|
||||
{
|
||||
"operation": "create-collection" | "delete-collection",
|
||||
"user": "user123",
|
||||
"collection": "documents-2024"
|
||||
}
|
||||
```
|
||||
|
||||
~~**Архитектура очередей:**~~
|
||||
~~**Очередь управления векторными хранилищами** (`vector-storage-management`): векторные/эмбеддинговые хранилища~~
|
||||
~~**Очередь управления хранилищами объектов** (`object-storage-management`): хранилища объектов/документов~~
|
||||
~~**Очередь управления графовыми хранилищами** (`triples-storage-management`): графовые/RDF хранилища~~
|
||||
~~**Очередь обработки ответов хранилища** (`storage-management-response`): все ответы отправляются сюда~~
|
||||
|
||||
**Текущая реализация:**
|
||||
|
||||
Все бэкенды хранилищ теперь используют `CollectionConfigHandler`:
|
||||
**Интеграция с системой push-уведомлений конфигурации**: службы хранилищ регистрируются для получения уведомлений об изменениях конфигурации
|
||||
**Автоматическая синхронизация**: коллекции создаются/удаляются на основе изменений конфигурации
|
||||
**Декларативная модель**: коллекции определены в службе конфигурации, бэкенды синхронизируются для соответствия
|
||||
**Отсутствие запросов/ответов**: устраняет накладные расходы на координацию и отслеживание ответов
|
||||
**Отслеживание состояния коллекций**: поддерживается через кэш `known_collections`
|
||||
**Идемпотентные операции**: безопасно обрабатывать одну и ту же конфигурацию несколько раз
|
||||
|
||||
Каждый бэкенд хранилища реализует:
|
||||
`create_collection(user: str, collection: str, metadata: dict)` - Создание структур коллекций
|
||||
`delete_collection(user: str, collection: str)` - Удаление всех данных коллекций
|
||||
`collection_exists(user: str, collection: str) -> bool` - Проверка перед записью
|
||||
|
||||
#### Рефакторинг графового хранилища Cassandra
|
||||
|
||||
В рамках этой реализации графовое хранилище Cassandra будет переработано с модели "таблица на коллекцию" на унифицированную модель "одна таблица":
|
||||
|
||||
**Текущая архитектура:**
|
||||
Keyspace на пользователя, отдельная таблица на коллекцию
|
||||
Схема: `(s, p, o)` с `PRIMARY KEY (s, p, o)`
|
||||
Имена таблиц: коллекции пользователя становятся отдельными таблицами Cassandra
|
||||
|
||||
**Новая архитектура:**
|
||||
Keyspace на пользователя, одна таблица "triples" для всех коллекций
|
||||
Схема: `(collection, s, p, o)` с `PRIMARY KEY (collection, s, p, o)`
|
||||
Изоляция коллекций через партиционирование коллекций
|
||||
|
||||
**Необходимые изменения:**
|
||||
|
||||
1. **Рефакторинг класса TrustGraph** (`trustgraph/direct/cassandra.py`):
|
||||
Удалить параметр `table` из конструктора, использовать фиксированную таблицу "triples"
|
||||
Добавить параметр `collection` ко всем методам
|
||||
Обновить схему для включения коллекции в качестве первого столбца
|
||||
**Обновления индексов**: Будут созданы новые индексы для поддержки всех 8 шаблонов запросов:
|
||||
Индекс на `(s)` для запросов на основе субъекта
|
||||
Индекс на `(p)` для запросов на основе предиката
|
||||
Индекс на `(o)` для запросов на основе объекта
|
||||
Обратите внимание: Cassandra не поддерживает многоколоночные вторичные индексы, поэтому это одноколоночные индексы
|
||||
|
||||
**Производительность шаблонов запросов**:
|
||||
✅ `get_all()` - сканирование раздела на `collection`
|
||||
✅ `get_s(s)` - эффективно использует первичный ключ (`collection, s`)
|
||||
✅ `get_p(p)` - использует `idx_p` с фильтрацией `collection`
|
||||
✅ `get_o(o)` - использует `idx_o` с фильтрацией `collection`
|
||||
✅ `get_sp(s, p)` - эффективно использует первичный ключ (`collection, s, p`)
|
||||
⚠️ `get_po(p, o)` - требует `ALLOW FILTERING` (использует либо `idx_p`, либо `idx_o` плюс фильтрацию)
|
||||
✅ `get_os(o, s)` - использует `idx_o` с дополнительной фильтрацией на `s`
|
||||
✅ `get_spo(s, p, o)` - эффективно использует полный первичный ключ
|
||||
|
||||
**Примечание об ALLOW FILTERING**: Шаблон запроса `get_po` требует `ALLOW FILTERING`, поскольку ему необходимы ограничения как предиката, так и объекта без подходящего составного индекса. Это допустимо, поскольку этот шаблон запроса менее распространен, чем запросы на основе субъекта, в типичном использовании хранилища тройных данных.
|
||||
|
||||
2. **Обновления модуля записи данных** (`trustgraph/storage/triples/cassandra/write.py`):
|
||||
Поддерживать одно соединение TrustGraph на пользователя вместо одного соединения на (пользователь, коллекция)
|
||||
Передавать коллекцию в операции вставки
|
||||
Улучшенное использование ресурсов за счет меньшего количества соединений
|
||||
|
||||
3. **Обновления сервиса запросов** (`trustgraph/query/triples/cassandra/service.py`):
|
||||
Одно соединение TrustGraph на пользователя
|
||||
Передавать коллекцию во все операции запросов
|
||||
Сохранять ту же логику запросов с параметром коллекции
|
||||
|
||||
**Преимущества:**
|
||||
**Упрощенное удаление коллекций**: Удаление с использованием ключа раздела `collection` во всех 4 таблицах
|
||||
**Эффективность использования ресурсов**: Меньшее количество соединений с базой данных и объектов таблиц
|
||||
**Операции, охватывающие несколько коллекций**: Легче реализовать операции, охватывающие несколько коллекций
|
||||
**Согласованная архитектура**: Соответствует унифицированному подходу к метаданным коллекций
|
||||
**Проверка коллекций**: Легко проверить существование коллекции через таблицу `triples_collection`
|
||||
|
||||
Операции с коллекциями будут выполняться атомарно, где это возможно, и обеспечивать соответствующую обработку ошибок и проверку.
|
||||
|
||||
## Вопросы безопасности
|
||||
|
||||
Управление коллекциями требует соответствующей авторизации для предотвращения несанкционированного доступа или удаления коллекций. Контроль доступа будет соответствовать существующим моделям безопасности TrustGraph.
|
||||
|
||||
## Вопросы производительности
|
||||
|
||||
Операции перечисления коллекций могут требовать постраничной разбивки для сред с большим количеством коллекций. Запросы метаданных должны быть оптимизированы для распространенных шаблонов фильтрации.
|
||||
|
||||
## Стратегия тестирования
|
||||
|
||||
Комплексное тестирование будет охватывать:
|
||||
Рабочий процесс создания коллекции от начала до конца
|
||||
Синхронизация с хранилищем
|
||||
Проверка при записи для несуществующих коллекций
|
||||
Обработка запросов для несуществующих коллекций
|
||||
Каскадное удаление коллекций во всех хранилищах
|
||||
Обработка ошибок и сценарии восстановления
|
||||
Юнит-тесты для каждого хранилища
|
||||
Интеграционные тесты для операций между хранилищами
|
||||
|
||||
## Статус реализации
|
||||
|
||||
### ✅ Завершенные компоненты
|
||||
|
||||
1. **Сервис управления коллекциями Librarian** (`trustgraph-flow/trustgraph/librarian/collection_manager.py`)
|
||||
Операции CRUD (создание, чтение, обновление, удаление) метаданных коллекции
|
||||
Интеграция с таблицей метаданных коллекций Cassandra через `LibraryTableStore`
|
||||
Координация каскадного удаления коллекций во всех типах хранилищ
|
||||
Асинхронная обработка запросов/ответов с надлежащим управлением ошибками
|
||||
|
||||
2. **Схема метаданных коллекции** (`trustgraph-base/trustgraph/schema/services/collection.py`)
|
||||
Схемы `CollectionManagementRequest` и `CollectionManagementResponse`
|
||||
Схема `CollectionMetadata` для записей коллекций
|
||||
Определения тем очередей для запросов/ответов коллекции
|
||||
|
||||
3. **Схема управления хранилищем** (`trustgraph-base/trustgraph/schema/services/storage.py`)
|
||||
Схемы `StorageManagementRequest` и `StorageManagementResponse`
|
||||
Определены темы очередей для управления хранилищем
|
||||
Формат сообщения для операций с коллекциями на уровне хранилища
|
||||
|
||||
4. **Схема Cassandra для 4 таблиц** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py`)
|
||||
Составные ключи разделов для повышения производительности запросов
|
||||
Таблица `triples_collection` для запросов SPO и отслеживания удаления
|
||||
Реализовано удаление коллекций с использованием шаблона "чтение-затем-удаление"
|
||||
|
||||
### ✅ Миграция на конфигурационно-ориентированный шаблон - ЗАВЕРШЕНО
|
||||
|
||||
**Все хранилища были перенесены из шаблона на основе очереди на конфигурационно-ориентированный шаблон `CollectionConfigHandler`.**
|
||||
|
||||
Выполненные миграции:
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/neo4j/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/memgraph/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/falkordb/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
|
||||
Теперь все хранилища:
|
||||
Наследуют от `CollectionConfigHandler`
|
||||
Регистрируются для получения уведомлений об изменениях конфигурации через `self.register_config_handler(self.on_collection_config)`
|
||||
Реализуют `create_collection(user, collection, metadata)` и `delete_collection(user, collection)`
|
||||
Используют `collection_exists(user, collection)` для проверки перед записью
|
||||
Автоматически синхронизируются с изменениями сервиса конфигурации
|
||||
|
||||
Устаревшая инфраструктура на основе очереди удалена:
|
||||
✅ Удалены схемы `StorageManagementRequest` и `StorageManagementResponse`
|
||||
✅ Удалены определения тем управления хранилищем
|
||||
✅ Удален потребитель/производитель очереди управления хранилищем из всех хранилищ
|
||||
✅ Удалены обработчики `on_storage_management` из всех хранилищ
|
||||
410
docs/tech-specs/collection-management.sw.md
Normal file
410
docs/tech-specs/collection-management.sw.md
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Maelekezo ya Ufundi ya Usimamizi wa Mkusanyiko"
|
||||
parent: "Swahili (Beta)"
|
||||
---
|
||||
|
||||
# Maelekezo ya Ufundi ya Usimamizi wa Mkusanyiko
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Muhtasari
|
||||
|
||||
Maelekezo haya yanaelezea uwezo wa usimamizi wa mkusanyiko kwa TrustGraph, ambayo yanahitaji uundaji wa mkusanyiko unaoonekana na yanatoa udhibiti wa moja kwa moja wa mzunguko wa maisha wa mkusanyiko. Mkusanyiko lazima uundwe kwa uwazi kabla ya kutumika, kuhakikisha usawazishaji sahihi kati ya metadata ya msimamizi na kila mfumo wa kuhifadhi. Kipengele hiki kinaunga mkazo kwa matumizi manne makuu:
|
||||
|
||||
1. **Uundaji wa Mkusanyiko**: Unda mkusanyiko kwa uwazi kabla ya kuhifadhi data
|
||||
2. **Orodha ya Mkusanyiko**: Angalia mkusanyiko wote uliopo katika mfumo
|
||||
3. **Usimamizi wa Metadata ya Mkusanyiko**: Sasisha majina, maelezo, na lebo za mkusanyiko
|
||||
4. **Ufutaji wa Mkusanyiko**: Ondoa mkusanyiko na data inayohusiana katika aina zote za uhifadhi
|
||||
|
||||
## Lengo
|
||||
|
||||
**Uundaji wa Mkusanyiko unaoonekana**: Hakikisha mkusanyiko uundwe kabla ya data kuweza kuhifadhiwa
|
||||
**Usawazishaji wa Uhifadhi**: Hakikisha mkusanyiko umezaliwa katika mifumo yote ya uhifadhi (vektali, vitu, triplet)
|
||||
**Uonevu wa Mkusanyiko**: Wasaidie watumiaji kuorodhesha na kuchunguza mkusanyiko wote katika mazingira yao
|
||||
**Usafishaji wa Mkusanyiko**: Waruhusu kuondoa mkusanyiko ambao hauhitajiki tena
|
||||
**Mpangilio wa Mkusanyiko**: Unga lebo na lebo za mada kwa ajili ya ufuatiliaji na ugunduzi bora wa mkusanyiko
|
||||
**Usimamizi wa Metadata**: Unganisha metadata inayoeleweka na mkusanyiko kwa uwazi wa utendaji
|
||||
**Ugunduzi wa Mkusanyiko**: Ifanye iwe rahisi zaidi kupata mkusanyiko maalum kupitia utaratibu na utafutaji
|
||||
**Uwazi wa Utendaji**: Toa uonevu wazi wa mzunguko wa maisha na matumizi ya mkusanyiko
|
||||
**Usimamizi wa Rasilimali**: Wasaidie kusafisha mkusanyiko usiohitajika ili kuongeza matumizi ya rasilimali
|
||||
**Uadilifu wa Data**: Zuia mkusanyiko usio na uhusiano katika uhifadhi bila kufuatilia metadata
|
||||
|
||||
## Asili
|
||||
|
||||
Hapo awali, mkusanyiko katika TrustGraph uliundwa kwa njia isiyoonekana wakati wa operesheni za kupakia data, na kusababisha matatizo ya usawazishaji ambapo mkusanyiko ulikuwa na uwezekano wa kuwepo katika mifumo ya uhifadhi bila metadata inayolingana katika msimamizi. Hii ilisababisha changamoto za usimamizi na uwezekano wa data isiyo na uhusiano.
|
||||
|
||||
Mfumo wa uundaji wa mkusanyiko unaoonekana unafanya kazi na masuala haya kwa:
|
||||
Kuhitaji mkusanyiko uundwe kabla ya kutumika kupitia `tg-set-collection`
|
||||
Kutangaza uundaji wa mkusanyiko kwa mifumo yote ya uhifadhi
|
||||
Kuhifadhi hali iliyosawazishwa kati ya metadata ya msimamizi na uhifadhi
|
||||
Kuzuia uandishi kwenye mkusanyiko usio na uwepo
|
||||
Kutoa usimamizi wazi wa mzunguko wa maisha wa mkusanyiko
|
||||
|
||||
Maelekezo haya yanafafanua mfumo wa usimamizi wa mkusanyiko unaoonekana. Kwa kuhitaji uundaji wa mkusanyiko unaoonekana, TrustGraph huhakikisha:
|
||||
Mkusanyiko unafuatiliwa katika metadata ya msimamizi kuanzia uundaji
|
||||
Mifumo yote ya uhifadhi inajua mkusanyiko kabla ya kupokea data
|
||||
Hakuna mkusanyiko usio na uhusiano katika uhifadhi
|
||||
Uwazi wa utendaji na udhibiti wa mzunguko wa maisha wa mkusanyiko
|
||||
Usimamizi thabiti wa makosa wakati operesheni zinarejelea mkusanyiko usio na uwepo
|
||||
|
||||
## Ubunifu wa Kiufundi
|
||||
|
||||
### Usanifu
|
||||
|
||||
Mfumo wa usimamizi wa mkusanyiko utatekelezwa ndani ya miundombinu iliyopo ya TrustGraph:
|
||||
|
||||
1. **Jumuisha Huduma ya Msimamizi**
|
||||
Operesheni za usimamizi wa mkusanyiko zitaongezwa kwenye huduma iliyopo ya msimamizi
|
||||
Huduma mpya haihitajiki - inatumia mitindo iliyopo ya uthibitishaji na ufikiaji
|
||||
Inashughulikia orodha ya mkusanyiko, kufutwa, na usimamizi wa metadata
|
||||
|
||||
Moduli: trustgraph-librarian
|
||||
|
||||
2. **Jedwali la Metadata ya Mkusanyiko la Cassandra**
|
||||
Jedwali jipya katika nafasi ya funguo ya msimamizi iliyopo
|
||||
Inahifadhi metadata ya mkusanyiko na ufikiaji wa mtumiaji
|
||||
Ufunguo mkuu: (user_id, collection_id) kwa usawazishaji sahihi wa wateja wengi
|
||||
|
||||
Moduli: trustgraph-librarian
|
||||
|
||||
3. **Kifaa cha Amri cha Usimamizi wa Mkusanyiko**
|
||||
Kiwao cha amri kwa operesheni za mkusanyiko
|
||||
Inatoa orodha, kufuta, lebo, na amri za usimamizi wa lebo
|
||||
Inajumuisha na mfumo uliopo wa kifaa cha amri
|
||||
|
||||
Moduli: trustgraph-cli
|
||||
|
||||
### Mifano ya Data
|
||||
|
||||
#### Jedwali la Metadata ya Mkusanyiko la Cassandra
|
||||
|
||||
Metadata ya mkusanyiko itahifadhiwa katika jedwali lililopangwa la Cassandra katika nafasi ya funguo ya msimamizi:
|
||||
|
||||
```sql
|
||||
CREATE TABLE collections (
|
||||
user text,
|
||||
collection text,
|
||||
name text,
|
||||
description text,
|
||||
tags set<text>,
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
PRIMARY KEY (user, collection)
|
||||
);
|
||||
```
|
||||
|
||||
Muundo wa jedwali:
|
||||
**user** + **collection**: Ufunguo mkuu unaojumuisha unaohakikisha kutenganishwa kwa watumiaji
|
||||
**name**: Jina la mkusanyiko linaloweza kusomwa na binadamu
|
||||
**description**: Maelezo ya kina ya madhumuni ya mkusanyiko
|
||||
**tags**: Kundi la lebo kwa ajili ya uainishaji na kuchujwa
|
||||
**created_at**: Alama ya muda ya uundaji wa mkusanyiko
|
||||
**updated_at**: Alama ya muda ya mabadiliko ya mwisho
|
||||
|
||||
Mbinu hii inaruhusu:
|
||||
Usimamizi wa mkusanyiko wa wateja wengi pamoja na kutenganishwa kwa watumiaji
|
||||
Ufuatiliaji wa haraka kwa mtumiaji na mkusanyiko
|
||||
Mfumo wa lebo unaobadilika kwa ajili ya upangaji
|
||||
Ufuatiliaji wa mzunguko wa maisha kwa ajili ya ufahamu wa utendaji
|
||||
|
||||
#### Mzunguko wa Maisha wa Mkusanyiko
|
||||
|
||||
Mkusanyiko huundwa wazi katika mfumo wa usimamizi kabla ya shughuli za data zinaweza kuendelea:
|
||||
|
||||
1. **Uundaji wa Mkusanyiko** (Njia Mbili):
|
||||
|
||||
**Njia A: Uundaji unaoanzishwa na Mtumiaji** kupitia `tg-set-collection`:
|
||||
Mtumiaji hutoa kitambulisho cha mkusanyiko, jina, maelezo, na lebo
|
||||
Mfumo wa usimamizi huunda rekodi ya metadata katika meza ya `collections`
|
||||
Mfumo wa usimamizi hutuma "unda-mkusanyiko" kwa kila mfumo wa kuhifadhi
|
||||
Mifumo yote ya kuhifadhi huunda mkusanyiko na kuthibitisha mafanikio
|
||||
Mkusanyiko sasa uko tayari kwa shughuli za data
|
||||
|
||||
**Njia B: Uundaji Otomatiki wakati wa Uwasilishaji wa Hati**:
|
||||
Mtumiaji huwasilisha hati inayobainisha kitambulisho cha mkusanyiko
|
||||
Mfumo wa usimamizi huhakikisha ikiwa mkusanyiko umejumuishwa katika meza ya metadata
|
||||
Ikiwa haujumuishwa: Mfumo wa usimamizi huunda metadata na mipangilio chache (jina=kitambulisho_cha_mkusanyiko, maelezo/lebo tupu)
|
||||
Mfumo wa usimamizi hutuma "unda-mkusanyiko" kwa kila mfumo wa kuhifadhi
|
||||
Mifumo yote ya kuhifadhi huunda mkusanyiko na kuthibitisha mafanikio
|
||||
Ufuatiliaji wa hati unaendelea na mkusanyiko sasa umeanzishwa
|
||||
|
||||
Njia zote mbili zinahakikisha kuwa mkusanyiko umejumuishwa katika metadata ya mfumo wa usimamizi NA katika mifumo yote ya kuhifadhi kabla ya shughuli za data.
|
||||
|
||||
2. **Uthibitisho wa Uhifadhi**: Shughuli za kuandika zinathibitisha kuwa mkusanyiko umejumuishwa:
|
||||
Mifumo ya kuhifadhi huhakikisha hali ya mkusanyiko kabla ya kukubali kuandika
|
||||
Kuandika kwa mkusanyiko usiojumuishwa kunarudisha kosa
|
||||
Hii inazuia kuandika moja kwa moja ambayo yanaweza kuepuka mantiki ya uundaji wa mkusanyiko ya mfumo wa usimamizi
|
||||
|
||||
3. **Tabia ya Ufuatiliaji**: Shughuli za kufuatilia hushughulikia mkusanyiko usiojumuishwa kwa utulivu:
|
||||
Ufuatiliaji kwa mkusanyiko usiojumuishwa hurudisha matokeo tupu
|
||||
Hakuna kosa linalorushwa kwa shughuli za kufuatilia
|
||||
Inaruhusu uchunguzi bila kuhitaji mkusanyiko kuwepo
|
||||
|
||||
4. **Sasisho za Metadata**: Watumiaji wanaweza kusasisha metadata ya mkusanyiko baada ya uundaji:
|
||||
Sasisha jina, maelezo, na lebo kupitia `tg-set-collection`
|
||||
Sasisho hutumika kwa metadata ya mfumo wa usimamizi pekee
|
||||
Mifumo ya kuhifadhi yanaendelea kuweka mkusanyiko lakini sasisho za metadata hazisambazwi
|
||||
|
||||
5. **Ufutaji Wazi**: Watumiaji huondoa mkusanyiko kupitia `tg-delete-collection`:
|
||||
Mfumo wa usimamizi hutuma "ondoa-mkusanyiko" kwa kila mfumo wa kuhifadhi
|
||||
Inasubiri uthibitisho kutoka kwa mifumo yote ya kuhifadhi
|
||||
Huondoa rekodi ya metadata ya mfumo wa usimamizi tu baada ya kusafishwa kwa uhifadhi kukamilika
|
||||
Inahakikisha hakuna data iliyoachwa katika uhifadhi
|
||||
|
||||
**Kanuni Muhimu**: Mfumo wa usimamizi ndio sehemu pekee ya udhibiti kwa uundaji wa mkusanyiko. Iwe iliyoanzishwa na amri ya mtumiaji au uwasilishaji wa hati, mfumo wa usimamizi huhakikisha ufuatiliaji sahihi wa metadata na usawazishaji wa mfumo wa kuhifadhi kabla ya kuruhusu shughuli za data.
|
||||
|
||||
Shughuli zinazohitajika:
|
||||
**Unda Mkusanyiko**: Shughuli ya mtumiaji kupitia `tg-set-collection` AU otomatiki wakati wa uwasilishaji wa hati
|
||||
**Sasisha Metadata ya Mkusanyiko**: Shughuli ya mtumiaji ili kurekebisha jina, maelezo, na lebo
|
||||
**Ondoa Mkusanyiko**: Shughuli ya mtumiaji ili kuondoa mkusanyiko na data yake katika maduka yote
|
||||
**Orodha ya Mkusanyiko**: Shughuli ya mtumiaji ili kuona mkusanyiko pamoja na kuchujwa kwa lebo
|
||||
|
||||
#### Usimamizi wa Mkusanyiko wa Maduka Mengi
|
||||
|
||||
Mkusanyiko huwepo katika mifumo tofauti ya kuhifadhi katika TrustGraph:
|
||||
**Maduka ya Vifaa** (Qdrant, Milvus, Pinecone): Kuhifadhi vifaa na data ya vifaa
|
||||
**Maduka ya Vitu** (Cassandra): Kuhifadhi hati na data ya faili
|
||||
**Maduka ya Vitatu** (Cassandra, Neo4j, Memgraph, FalkorDB): Kuhifadhi data ya grafu/RDF
|
||||
|
||||
Kila aina ya duka inatekeleza:
|
||||
**Ufuatiliaji wa Hali ya Mkusanyiko**: Kuhifadhi habari kuhusu makusanyiko ambayo yamepo.
|
||||
**Uundaji wa Mkusanyiko**: Kukubali na kuchakata "unda-mkusanyiko" shughuli.
|
||||
**Uthibitisho wa Mkusanyiko**: Angalia ikiwa mkusanyiko unapatikana kabla ya kukubali uandikaji.
|
||||
**Ufutaji wa Mkusanyiko**: Ondoa data yote kwa mkusanyiko uliotajwa.
|
||||
|
||||
Huduma ya mhakimishi inaangazia shughuli za mkusanyiko katika aina zote za kuhifadhi, kuhakikisha:
|
||||
Makusanyiko yanaundwa katika mifumo yote ya nyuma kabla ya matumizi.
|
||||
Mifumo yote ya nyuma inaonyesha uundaji kabla ya kurejesha mafanikio.
|
||||
Mzunguko wa mkusanyiko umeunganishwa katika aina tofauti za uhifadhi.
|
||||
Usimamizi thabiti wa makosa wakati makusanyiko hayapo.
|
||||
|
||||
#### Ufuatiliaji wa Hali ya Mkusanyiko kwa Aina ya Uhifadhi
|
||||
|
||||
Kila mfumo wa nyuma wa uhifadhi unafuatilia hali ya mkusanyiko tofauti kulingana na uwezo wake:
|
||||
|
||||
**Duka la Maneno la Cassandra:**
|
||||
Hutumia meza iliyopo `triples_collection`.
|
||||
Huunda alama ya mfumo wakati mkusanyiko unaundwa.
|
||||
Uulizo: `SELECT collection FROM triples_collection WHERE collection = ? LIMIT 1`.
|
||||
Uchunguzi wa sehemu moja kwa uwepo wa mkusanyiko.
|
||||
|
||||
**Vifaa vya Vector vya Qdrant/Milvus/Pinecone:**
|
||||
API za asili za mkusanyiko hutoa uchunguzi wa uwepo.
|
||||
Makusanyiko yanaundwa na usanidi sahihi wa vector.
|
||||
Njia `collection_exists()` hutumia API ya uhifadhi.
|
||||
Uundaji wa mkusanyiko unafanya uthibitisho wa mahitaji ya kipimo.
|
||||
|
||||
**Vifaa vya Grafu vya Neo4j/Memgraph/FalkorDB:**
|
||||
Hutumia nodi `:CollectionMetadata` kufuatilia makusanyiko.
|
||||
Vipengele vya nodi: `{user, collection, created_at}`.
|
||||
Uulizo: `MATCH (c:CollectionMetadata {user: $user, collection: $collection})`.
|
||||
Tofauti na nodi za data kwa kutenganisha vizuri.
|
||||
Inaruhusu orodha na uthibitisho wa mkusanyiko kuwa rahisi.
|
||||
|
||||
**Duka la Vitu la Cassandra:**
|
||||
Hutumia meza ya metadata ya mkusanyiko au mistari ya alama.
|
||||
Mfano sawa na duka la maneno.
|
||||
Inathibitisha mkusanyiko kabla ya uandikaji wa hati.
|
||||
|
||||
### API
|
||||
|
||||
API za Usimamizi wa Mkusanyiko (Mhakimishi):
|
||||
**Unda/Boresha Mkusanyiko**: Unda mkusanyiko mpya au boresha metadata iliyopo kupitia `tg-set-collection`.
|
||||
**Orodha ya Makusanyiko**: Pata makusanyiko kwa mtumiaji na uchujaji wa tag wa hiari.
|
||||
**Futa Mkusanyiko**: Ondoa mkusanyiko na data inayohusiana, na kuenea kwa aina zote za kuhifadhi.
|
||||
|
||||
API za Usimamizi wa Uhifadhi (Wote Wasindikaji wa Uhifadhi):
|
||||
**Unda Mkusanyiko**: Shughuli ya "unda-mkusanyiko", weka mkusanyiko katika uhifadhi.
|
||||
**Futa Mkusanyiko**: Shughuli ya "futa-mkusanyiko", ondoa data yote ya mkusanyiko.
|
||||
**Angalia Ikiwa Mkusanyiko Upo**: Uthibitisho wa ndani kabla ya kukubali shughuli za uandikaji.
|
||||
|
||||
API za Uendeshaji wa Data (Tabia Imebadilishwa):
|
||||
**API za Uandikaji**: Thibitisha kuwa mkusanyiko unapatikana kabla ya kukubali data, na uweke makosa ikiwa haipo.
|
||||
**API za Uulizo**: Rejesha matokeo tupu kwa makusanyiko ambayo hayapo bila makosa.
|
||||
|
||||
### Maelezo ya Utendaji
|
||||
|
||||
Utendaji utafuata mifumo iliyopo ya TrustGraph kwa ujumuishaji wa huduma na muundo wa amri ya CLI.
|
||||
|
||||
#### Ufufuo wa Ufufuo wa Mkusanyiko
|
||||
|
||||
Wakati mtumiaji anaanzisha ufutaji wa mkusanyiko kupitia huduma ya mhakimishi:
|
||||
|
||||
1. **Uthibitisho wa Metadata**: Thibitisha kuwa mkusanyiko unapatikana na mtumiaji ana ruhusa ya kufuta.
|
||||
2. **Ufufuo wa Duka**: Mhakimishi inaangazia ufutaji katika waandishi wote wa duka:
|
||||
Mwandishi wa duka la vector: Ondoa embeddings na fahirisi za vector kwa mtumiaji na mkusanyiko.
|
||||
Mwandishi wa duka la kitu: Ondoa hati na faili kwa mtumiaji na mkusanyiko.
|
||||
Mwandishi wa duka la maneno: Ondoa data ya grafu na maneno kwa mtumiaji na mkusanyiko.
|
||||
3. **Usafishaji wa Metadata**: Ondoa rekodi ya metadata ya mkusanyiko kutoka Cassandra.
|
||||
4. **Usimamizi wa Makosa**: Ikiwa ufutaji wowote wa duka hufeli, dhibiti uthabiti kupitia utaratibu wa kurejesha au kujaribu tena.
|
||||
|
||||
#### Kiolesura cha Usimamizi wa Mkusanyiko
|
||||
|
||||
**⚠️ MFUMO WA KALE - IMEBADILISHWA NA MFUMO WA MSINGI WA MSINGI**
|
||||
|
||||
Arkitektura iliyoelezwa ya msingi ya folyo imebadilishwa na mbinu iliyosimama na usanidi inayotumia `CollectionConfigHandler`. Mifumo yote ya nyuma ya uhifadhi sasa hupokea sasisho za mkusanyiko kupitia ujumbe wa kushinikiza usanidi badala ya folyo maalum za usimamizi.
|
||||
|
||||
~~Wote waandishi wa duka inatekeleza kiolesura cha kawaida cha usimamizi wa mkusanyiko na schema ya kawaida:~~
|
||||
|
||||
~~**Schema ya Ujumbe (`StorageManagementRequest`):**~~
|
||||
```json
|
||||
{
|
||||
"operation": "create-collection" | "delete-collection",
|
||||
"user": "user123",
|
||||
"collection": "documents-2024"
|
||||
}
|
||||
```
|
||||
|
||||
~~**Usawa wa Mifumo:**~~
|
||||
~~**Kikao cha Usimamizi wa Hifadhi ya Data (Vector Store)** (`vector-storage-management`): Hifadhi za vector/embedding~~
|
||||
~~**Kikao cha Usimamizi wa Hifadhi ya Data (Object Store)** (`object-storage-management`): Hifadhi za data/nyaraka~~
|
||||
~~**Kikao cha Usimamizi wa Hifadhi ya Data (Triple Store)** (`triples-storage-management`): Hifadhi za grafu/RDF~~
|
||||
~~**Kikao cha Majibu ya Hifadhi ya Data** (`storage-management-response`): Majibu yote hutumwa hapa~~
|
||||
|
||||
**Utendaji Sasa:**
|
||||
|
||||
Mifumo yote ya hifadhi ya data sasa hutumia `CollectionConfigHandler`:
|
||||
**Uunganishaji wa Uhamisho wa Config**: Huduma za hifadhi ya data huzungushwa kwa arifa za uhamisho wa config
|
||||
**Usawajili Otomatiki**: Mkusanyiko huundwa/kufutwa kulingana na mabadiliko ya config
|
||||
**Mfumo wa Kielelezo:** Mkusanyiko umeinuliwa katika huduma ya config, hifadhi ya data husawazishwa ili kuendana
|
||||
**Hakuna Ombi/Jibu:** Huondoa gharama ya uratibu na ufuatiliaji wa majibu
|
||||
**Ufuatiliaji wa Hali ya Mkusanyiko:** Inahifadhiwa kupitia kumbukumbu `known_collections`
|
||||
**Operesheni za Idempotent:** Ni salama kuchakata config sawa mara nyingi
|
||||
|
||||
Kila mfumo wa hifadhi ya data unatekeleza:
|
||||
`create_collection(user: str, collection: str, metadata: dict)` - Unda miundo ya mkusanyiko
|
||||
`delete_collection(user: str, collection: str)` - Ondoa data yote ya mkusanyiko
|
||||
`collection_exists(user: str, collection: str) -> bool` - Thibitisha kabla ya kuandika
|
||||
|
||||
#### Urekebishaji wa Hifadhi ya Data ya Triple ya Cassandra
|
||||
|
||||
Kama sehemu ya utekelezaji huu, hifadhi ya data ya triple ya Cassandra itarekebishwa kutoka kwa mfumo wa jedwali-kwa-mkusanyiko hadi mfumo wa jedwali lililo na muundo mmoja:
|
||||
|
||||
**Muundo Sasa:**
|
||||
Keyspace kwa kila mtumiaji, jedwali tofauti kwa kila mkusanyiko
|
||||
Schema: `(s, p, o)` na `PRIMARY KEY (s, p, o)`
|
||||
Majina ya jedwali: mkusanyiko wa mtumiaji unakuwa jedwali tofauti za Cassandra
|
||||
|
||||
**Muundo Mpya:**
|
||||
Keyspace kwa kila mtumiaji, jedwali moja la "triples" kwa mkusanyiko wote
|
||||
Schema: `(collection, s, p, o)` na `PRIMARY KEY (collection, s, p, o)`
|
||||
Utengano wa mkusanyiko kupitia ugawaji wa mkusanyiko
|
||||
|
||||
**Mabadiliko Yanayohitajika:**
|
||||
|
||||
1. **Urekebishaji wa Darasa la TrustGraph** (`trustgraph/direct/cassandra.py`):
|
||||
Ondoa parameter `table` kutoka kwa konstrukata, tumia jedwali "triples" lililo na muundo mmoja
|
||||
Ongeza parameter `collection` kwa mbinu zote
|
||||
Sasisha schema ili kujumuisha mkusanyiko kama safu ya kwanza
|
||||
**Sasisho za Indexi:** Indexi mpya zitaundwa ili kusaidia mifumo yote 8 ya swali:
|
||||
Indexi kwenye `(s)` kwa maswali yanayohusiana na mada
|
||||
Indexi kwenye `(p)` kwa maswali yanayohusiana na sifa
|
||||
Indexi kwenye `(o)` kwa maswali yanayohusiana na kitu
|
||||
Kumbuka: Cassandra haitumii indexi za sekondari za safu nyingi, kwa hivyo hizi ni indexi za safu moja
|
||||
|
||||
**Utendaji wa Mfumo wa Swali:**
|
||||
✅ `get_all()` - skani ya ugawaji kwenye `collection`
|
||||
✅ `get_s(s)` - hutumia ufunguo mkuu kwa ufanisi (`collection, s`)
|
||||
✅ `get_p(p)` - hutumia `idx_p` na `collection` ya kuchujwa
|
||||
✅ `get_o(o)` - hutumia `idx_o` na `collection` ya kuchujwa
|
||||
✅ `get_sp(s, p)` - hutumia ufunguo mkuu kwa ufanisi (`collection, s, p`)
|
||||
⚠️ `get_po(p, o)` - inahitaji `ALLOW FILTERING` (inatumia ama `idx_p` au `idx_o` pamoja na kuchujwa)
|
||||
✅ `get_os(o, s)` - hutumia `idx_o` na kuchujwa cha ziada kwenye `s`
|
||||
✅ `get_spo(s, p, o)` - hutumia ufunguo mkuu kwa ufanisi
|
||||
|
||||
**Kumbuka kuhusu ALLOW FILTERING:** Mfumo wa swali `get_po` unahitaji `ALLOW FILTERING` kwa sababu unahitaji sifa na kikomo cha kitu bila indexi ya pamoja inayofaa. Hii inakubalika kwa sababu mfumo huu wa swali ni mdogo kuliko maswali yanayohusiana na mada katika matumizi ya kawaida ya hifadhi ya data ya triple
|
||||
|
||||
2. **Sasisho za Mwandishi wa Hifadhi ya Data** (`trustgraph/storage/triples/cassandra/write.py`):
|
||||
Dumishe muunganisho mmoja wa TrustGraph kwa kila mtumiaji badala ya kwa kila (mtumiaji, mkusanyiko)
|
||||
Pasa mkusanyiko kwenye operesheni za kuingiza
|
||||
Matumizi bora ya rasilimali kwa muunganisho mdogo
|
||||
|
||||
3. **Sasisho za Huduma ya Swali** (`trustgraph/query/triples/cassandra/service.py`):
|
||||
Muunganisho mmoja wa TrustGraph kwa kila mtumiaji
|
||||
Pasa mkusanyiko kwa operesheni zote za swali
|
||||
Dumishe mantiki sawa ya swali na parameter ya mkusanyiko
|
||||
|
||||
**Faida:**
|
||||
**Uondoo Ulioboreshwa wa Mkusanyiko:** Ondoa kwa kutumia ufunguo wa ugawaji `collection` katika meza zote 4
|
||||
**Ufanisi wa Rasilimali:** Muunganisho mdogo wa hifadhi ya data na vitu vya jedwali
|
||||
**Operesheni za Mkusanyiko Mbalimbali:** Ni rahisi kutekeleza operesheni zinazohusisha mkusanyiko mwingi
|
||||
**Muundo Uliofanana:** Inalingana na mbinu iliyounganishwa ya metadata ya mkusanyiko
|
||||
**Uthibitisho wa Mkusanyiko:** Ni rahisi kuangalia uwepo wa mkusanyiko kupitia jedwali `triples_collection`
|
||||
|
||||
Operesheni za ukusanyaji zitakuwa za atomiki ambapo inawezekana na hutoa utunzaji wa makosa unaofaa na uthibitisho.
|
||||
|
||||
## Masuala ya Usalama
|
||||
|
||||
Operesheni za usimamizi wa ukusanyaji zinahitaji idhini inayofaa ili kuzuia ufikiaji usioidhinishwa au kufutwa kwa ukusanyaji. Udhibiti wa ufikiaji utalingana na modeli za usalama za TrustGraph zilizopo.
|
||||
|
||||
## Masuala ya Utendaji
|
||||
|
||||
Operesheni za kuorodhesha ukusanyaji zinaweza kuhitaji upangishaji katika mazingira yenye idadi kubwa ya ukusanyaji. Maswali ya metadata yanapaswa kuboreshwa kwa mifumo ya kawaida ya kuchujwa.
|
||||
|
||||
## Mkakati wa Majaribio
|
||||
|
||||
Majaribio kamili yataangazia:
|
||||
Mchakato wa kuunda ukusanyaji kutoka mwanzo hadi mwisho
|
||||
Usawazishaji wa mfumo wa kuhifadhi data
|
||||
Uthibitisho wa kuandika kwa ukusanyaji usiopo
|
||||
Usimamizi wa maswali ya ukusanyaji usiopo
|
||||
Ufutilishaji wa ukusanyaji unaoenea katika maduka yote
|
||||
Usimamizi wa makosa na hali ya uponyaji
|
||||
Majaribio ya kitengo kwa kila mfumo wa kuhifadhi data
|
||||
Majaribio ya ujumuishaji kwa operesheni za duka nyingi
|
||||
|
||||
## Hali ya Utendaji
|
||||
|
||||
### ✅ Vipengele Vilivyokamilika
|
||||
|
||||
1. **Huduma ya Usimamizi wa Ukusanyaji ya Librarian** (`trustgraph-flow/trustgraph/librarian/collection_manager.py`)
|
||||
Operesheni za CRUD za metadata ya ukusanyaji (orodha, sasisha, futa)
|
||||
Ujumuishaji wa jedwali la metadata ya ukusanyaji ya Cassandra kupitia `LibraryTableStore`
|
||||
Uratibu wa kufutiliwa kwa ukusanyaji unaoenea katika aina zote za uhifadhi
|
||||
Usimamizi wa ombi/jibu lisilo na wakati pamoja na usimamizi wa makosa unaofaa
|
||||
|
||||
2. **Mfumo wa Metadata wa Ukusanyaji** (`trustgraph-base/trustgraph/schema/services/collection.py`)
|
||||
Mfumo wa `CollectionManagementRequest` na `CollectionManagementResponse`
|
||||
Mfumo wa `CollectionMetadata` kwa rekodi za ukusanyaji
|
||||
Ufafanuzi wa mada ya folyo ya ombi/jibu la ukusanyaji
|
||||
|
||||
3. **Mfumo wa Usimamizi wa Uhifadhi** (`trustgraph-base/trustgraph/schema/services/storage.py`)
|
||||
Mfumo wa `StorageManagementRequest` na `StorageManagementResponse`
|
||||
Mada za folyo za usimamizi wa uhifadhi zimefafanuliwa
|
||||
Muundo wa ujumbe kwa operesheni za ukusanyaji za kiwango cha uhifadhi
|
||||
|
||||
4. **Mfumo wa Jedwali la Cassandra 4** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py`)
|
||||
Funguo za sehemu mchanganyiko kwa utendaji wa swali
|
||||
Jedwali la `triples_collection` kwa maswali ya SPO na kufuatilia kufutiliwa
|
||||
Ufutilishaji wa ukusanyaji umetekelezwa na mfumo wa kusoma kisha kufuta
|
||||
|
||||
### ✅ Uhamishaji kwa Mfumo Kulingana na Config - UMEKABALIKA
|
||||
|
||||
**Maduka yote ya uhifadhi yamehamishwa kutoka kwa mfumo unaotegemea folyo hadi kwa mfumo unaotegemea config wa `CollectionConfigHandler`.**
|
||||
|
||||
Uhamishaji uliokamilika:
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/neo4j/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/memgraph/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/falkordb/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
|
||||
Maduka yote sasa:
|
||||
Yanachukua kutoka `CollectionConfigHandler`
|
||||
Yamesajiliwa kwa arifa za config inayoboreshwa kupitia `self.register_config_handler(self.on_collection_config)`
|
||||
Yatekeleza `create_collection(user, collection, metadata)` na `delete_collection(user, collection)`
|
||||
Yatumie `collection_exists(user, collection)` ili kuthibitisha kabla ya kuandika
|
||||
Yanasawazishwa kiotomatiki na mabadiliko ya huduma ya config
|
||||
|
||||
Infrastrakturu ya zamani inayotegemea folyo imeondolewa:
|
||||
✅ Mfumo wa `StorageManagementRequest` na `StorageManagementResponse` umeondolewa
|
||||
✅ Ufafanuzi wa mada za usimamizi wa uhifadhi umeondolewa
|
||||
✅ Mtumiaji/mtayarishaji wa folyo kutoka kwa maduka yote umeondolewa
|
||||
✅ Wasimamizi wa `on_storage_management` kutoka kwa maduka yote umeondolewa
|
||||
410
docs/tech-specs/collection-management.tr.md
Normal file
410
docs/tech-specs/collection-management.tr.md
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Koleksiyon Yönetimi Teknik Özellikleri"
|
||||
parent: "Turkish (Beta)"
|
||||
---
|
||||
|
||||
# Koleksiyon Yönetimi Teknik Özellikleri
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Genel Bakış
|
||||
|
||||
Bu özellik, TrustGraph için koleksiyon yönetimi yeteneklerini tanımlar ve açık koleksiyon oluşturulmasını gerektirir ve koleksiyon yaşam döngüsü üzerinde doğrudan kontrol sağlar. Koleksiyonlar, uygun veri ambarı ve tüm depolama arka uçları arasındaki senkronizasyonu sağlamak için kullanmadan önce açıkça oluşturulmalıdır. Bu özellik, dört birincil kullanım senaryosunu destekler:
|
||||
|
||||
1. **Koleksiyon Oluşturma**: Veri depolamadan önce koleksiyonları açıkça oluşturun
|
||||
2. **Koleksiyon Listeleme**: Sistemdeki mevcut tüm koleksiyonları görüntüleyin
|
||||
3. **Koleksiyon Meta Veri Yönetimi**: Koleksiyon adlarını, açıklamalarını ve etiketlerini güncelleyin
|
||||
4. **Koleksiyon Silme**: Koleksiyonları ve bunlara bağlı verileri tüm depolama türlerinden kaldırın
|
||||
|
||||
## Hedefler
|
||||
|
||||
**Açık Koleksiyon Oluşturma**: Verilerin depolanabilmesi için koleksiyonların oluşturulmasını gerektirir
|
||||
**Depolama Senkronizasyonu**: Koleksiyonların tüm depolama arka uçlarında (vektörler, nesneler, üçlüler) mevcut olduğundan emin olun
|
||||
**Koleksiyon Görünürlüğü**: Kullanıcıların ortamlarındaki tüm koleksiyonları listelemesini ve incelemesini sağlayın
|
||||
**Koleksiyon Temizleme**: Artık gerekli olmayan koleksiyonların silinmesine izin verin
|
||||
**Koleksiyon Organizasyonu**: Daha iyi koleksiyon takibi ve keşfi için etiketleri ve kategorileri destekleyin
|
||||
**Meta Veri Yönetimi**: İşletimsel açıklık için koleksiyonlarla anlamlı meta verileri ilişkilendirin
|
||||
**Koleksiyon Keşfi**: Filtreleme ve arama yoluyla belirli koleksiyonları bulmayı kolaylaştırın
|
||||
**İşletim Şeffaflığı**: Koleksiyon yaşam döngüsü ve kullanımı hakkında net görünürlük sağlayın
|
||||
**Kaynak Yönetimi**: Kullanılmayan koleksiyonları temizleyerek kaynak kullanımını optimize etmeyi sağlayın
|
||||
**Veri Bütünlüğü**: Meta veri takibi olmadan depolamada yetim koleksiyonların oluşmasını önleyin
|
||||
|
||||
## Arka Plan
|
||||
|
||||
Geçmişte, TrustGraph'taki koleksiyonlar, veri yükleme işlemleri sırasında örtülü olarak oluşturuluyordu ve bu da koleksiyonların depolama arka uçlarında, ancak kütüphanecide ilgili meta verilere sahip olmadan var olabileceği senkronizasyon sorunlarına yol açıyordu. Bu durum, yönetim zorlukları ve potansiyel olarak yetim veri sorunları yaratmıştır.
|
||||
|
||||
Açık koleksiyon oluşturma modeli, bu sorunları aşağıdaki şekilde ele alır:
|
||||
Koleksiyonların `tg-set-collection` aracılığıyla kullanmadan önce oluşturulmasını gerektirir
|
||||
Koleksiyon oluşturmayı tüm depolama arka uçlarına yayınlar
|
||||
Kütüphaneci meta verileri ile depolama arasındaki senkronize durumu korur
|
||||
Var olmayan koleksiyonlara yazmayı engeller
|
||||
Açık koleksiyon yaşam döngüsü yönetimi sağlar
|
||||
|
||||
Bu özellik, açık koleksiyon yönetimi modelini tanımlar. Açık koleksiyon oluşturmayı gerektirerek, TrustGraph şunları sağlar:
|
||||
Koleksiyonlar, oluşturulmadan itibaren kütüphaneci meta verilerinde takip edilir
|
||||
Tüm depolama arka uçları, verileri almadan önce koleksiyonların varlığından haberdardır
|
||||
Depolamada yetim koleksiyonların oluşması engellenir
|
||||
Koleksiyon yaşam döngüsü üzerinde açık işletimsel görünürlük ve kontrol sağlanır
|
||||
Var olmayan koleksiyonlara yapılan işlemlerde tutarlı hata işleme sağlanır
|
||||
|
||||
## Teknik Tasarım
|
||||
|
||||
### Mimari
|
||||
|
||||
Koleksiyon yönetimi sistemi, mevcut TrustGraph altyapısının içinde uygulanacaktır:
|
||||
|
||||
1. **Kütüphaneci Hizmeti Entegrasyonu**
|
||||
Koleksiyon yönetimi işlemleri, mevcut kütüphaneci hizmetine eklenecektir
|
||||
Yeni bir hizmet gerektirmez - mevcut kimlik doğrulama ve erişim kalıplarından yararlanır
|
||||
Koleksiyon listeleme, silme ve meta veri yönetimi işlemlerini işler
|
||||
|
||||
Modül: trustgraph-librarian
|
||||
|
||||
2. **Cassandra Koleksiyon Meta Veri Tablosu**
|
||||
Mevcut kütüphaneci anahtar alanındaki yeni bir tablo
|
||||
Kullanıcı kapsamlı erişim ile koleksiyon meta verilerini depolar
|
||||
Birincil anahtar: Doğru çoklu kiracılık için (user_id, collection_id)
|
||||
|
||||
Modül: trustgraph-librarian
|
||||
|
||||
3. **Koleksiyon Yönetimi CLI**
|
||||
Koleksiyon işlemleri için komut satırı arayüzü
|
||||
Listeleme, silme, etiketleme ve etiket yönetimi komutları sağlar
|
||||
Mevcut CLI çerçevesiyle entegre olur
|
||||
|
||||
Modül: trustgraph-cli
|
||||
|
||||
### Veri Modelleri
|
||||
|
||||
#### Cassandra Koleksiyon Meta Veri Tablosu
|
||||
|
||||
Koleksiyon meta verileri, kütüphaneci anahtar alanındaki yapılandırılmış bir Cassandra tablosunda saklanacaktır:
|
||||
|
||||
```sql
|
||||
CREATE TABLE collections (
|
||||
user text,
|
||||
collection text,
|
||||
name text,
|
||||
description text,
|
||||
tags set<text>,
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
PRIMARY KEY (user, collection)
|
||||
);
|
||||
```
|
||||
|
||||
Tablo yapısı:
|
||||
**user**: **collection**: Birincil bileşik anahtar, kullanıcı yalıtımını sağlar
|
||||
**name**: İnsan tarafından okunabilir koleksiyon adı
|
||||
**description**: Koleksiyonun amacının ayrıntılı açıklaması
|
||||
**tags**: Kategorizasyon ve filtreleme için etiket kümesi
|
||||
**created_at**: Koleksiyon oluşturma zaman damgası
|
||||
**updated_at**: Son değişiklik zaman damgası
|
||||
|
||||
Bu yaklaşım şunları sağlar:
|
||||
Kullanıcı yalıtımı ile çoklu kiracılı koleksiyon yönetimi
|
||||
Kullanıcı ve koleksiyon bazında verimli sorgulama
|
||||
Düzenleme için esnek etiketleme sistemi
|
||||
İşletimsel bilgiler için yaşam döngüsü takibi
|
||||
|
||||
#### Koleksiyon Yaşam Döngüsü
|
||||
|
||||
Koleksiyonlar, veri işlemlerine başlamadan önce kütüphanede açıkça oluşturulmalıdır:
|
||||
|
||||
1. **Koleksiyon Oluşturma** (İki Yol):
|
||||
|
||||
**Yol A: Kullanıcı Tarafından Başlatılan Oluşturma** `tg-set-collection` aracılığıyla:
|
||||
Kullanıcı, koleksiyon kimliği, adı, açıklaması ve etiketleri sağlar
|
||||
Kütüphane, `collections` tablosunda bir meta veri kaydı oluşturur
|
||||
Kütüphane, tüm depolama arka uçlarına "create-collection" mesajını gönderir
|
||||
Tüm depolama işlemcileri, koleksiyonu oluşturur ve başarıyı onaylar
|
||||
Koleksiyon artık veri işlemleri için hazırdır
|
||||
|
||||
**Yol B: Belge Gönderimi Üzerinde Otomatik Oluşturma**:
|
||||
Kullanıcı, bir koleksiyon kimliği belirten bir belge gönderir
|
||||
Kütüphane, koleksiyonun meta veri tablosunda mevcut olup olmadığını kontrol eder
|
||||
Yoksa: Kütüphane, varsayılanlarla (ad=koleksiyon_kimliği, boş açıklama/etiketler) bir meta veri oluşturur
|
||||
Kütüphane, tüm depolama arka uçlarına "create-collection" mesajını gönderir
|
||||
Tüm depolama işlemcileri, koleksiyonu oluşturur ve başarıyı onaylar
|
||||
Belge işleme, koleksiyonun artık oluşturulduğu şekilde devam eder
|
||||
|
||||
Her iki yol da, veri işlemlerine izin verilmeden önce koleksiyonun kütüphane meta verilerinde VE tüm depolama arka uçlarında mevcut olmasını sağlar.
|
||||
|
||||
2. **Depolama Doğrulama**: Yazma işlemleri, koleksiyonun mevcut olup olmadığını doğrular:
|
||||
Depolama işlemcileri, yazmayı kabul etmeden önce koleksiyonun durumunu kontrol eder
|
||||
Mevcut olmayan koleksiyonlara yapılan yazılar hata döndürür
|
||||
Bu, doğrudan yazmaların kütüphanenin koleksiyon oluşturma mantığını atlamasını engeller
|
||||
|
||||
3. **Sorgu Davranışı**: Sorgu işlemleri, mevcut olmayan koleksiyonları zarif bir şekilde işler:
|
||||
Mevcut olmayan koleksiyonlara yapılan sorgular boş sonuçlar döndürür
|
||||
Sorgu işlemleri için hata oluşmaz
|
||||
Koleksiyonun mevcut olması gerekmeksizin keşfetmeye olanak tanır
|
||||
|
||||
4. **Meta Veri Güncellemeleri**: Kullanıcılar, koleksiyon oluşturulduktan sonra koleksiyon meta verilerini güncelleyebilir:
|
||||
Adı, açıklamasını ve etiketleri `tg-set-collection` aracılığıyla güncelleyin
|
||||
Güncellemeler yalnızca kütüphane meta verilerine uygulanır
|
||||
Depolama arka uçları koleksiyonu korur, ancak meta veri güncellemeleri yayılmaz
|
||||
|
||||
5. **Açık Silme**: Kullanıcılar, koleksiyonları `tg-delete-collection` aracılığıyla siler:
|
||||
Kütüphane, tüm depolama arka uçlarına "delete-collection" mesajını gönderir
|
||||
Tüm depolama işlemcilerinden onay bekler
|
||||
Depolama temizliği tamamlandıktan SONRA yalnızca kütüphane meta veri kaydını siler
|
||||
Depoda hiçbir verinin kaybolmamasını sağlar
|
||||
|
||||
**Temel İlke**: Kütüphane, koleksiyon oluşturma için tek kontrol noktasıdır. Kullanıcı komutu veya belge gönderimi ile başlatılıp başlatılmadığına bakılmaksızın, kütüphane, veri işlemlerine izin vermeden önce uygun meta veri takibi ve depolama arka uç senkronizasyonunu sağlar.
|
||||
|
||||
Gerekli işlemler:
|
||||
**Koleksiyon Oluşturma**: `tg-set-collection` aracılığıyla kullanıcı işlemi VEYA belge gönderimi üzerine otomatik
|
||||
**Koleksiyon Meta Verilerini Güncelleme**: Adı, açıklaması ve etiketleri değiştirmek için kullanıcı işlemi
|
||||
**Koleksiyonu Silme**: Koleksiyonu ve tüm depolarda verilerini kaldırmak için kullanıcı işlemi
|
||||
**Koleksiyonları Listeleme**: Etiketlere göre filtreleme ile koleksiyonları görüntülemek için kullanıcı işlemi
|
||||
|
||||
#### Çoklu Depo Koleksiyon Yönetimi
|
||||
|
||||
Koleksiyonlar, TrustGraph'ta birden çok depolama arka uçunda bulunur:
|
||||
**Vektör Depoları** (Qdrant, Milvus, Pinecone): Gömme ve vektör verilerini depolar
|
||||
**Nesne Depoları** (Cassandra): Belge ve dosya verilerini depolar
|
||||
**Üçlü Depolar** (Cassandra, Neo4j, Memgraph, FalkorDB): Grafik/RDF verilerini depolar
|
||||
|
||||
Her bir mağaza türü aşağıdaki işlemleri uygular:
|
||||
**Koleksiyon Durumu Takibi**: Hangi koleksiyonların mevcut olduğunu takip etme
|
||||
**Koleksiyon Oluşturma**: "koleksiyon oluştur" işlemlerini kabul etme ve işleme alma
|
||||
**Koleksiyon Doğrulama**: Yazma işlemlerini kabul etmeden önce koleksiyonun varlığını kontrol etme
|
||||
**Koleksiyon Silme**: Belirtilen koleksiyon için tüm verileri silme
|
||||
|
||||
Kütüphaneci hizmeti, tüm mağaza türleri arasında koleksiyon işlemlerini koordine ederek şunları sağlar:
|
||||
Koleksiyonlar, kullanmadan önce tüm arka uçlarda oluşturulur
|
||||
Tüm arka uçlar, oluşturma işleminden sonra başarıyı doğrular
|
||||
Depolama türleri arasında senkronize koleksiyon yaşam döngüsü
|
||||
Koleksiyonlar mevcut olmadığında tutarlı hata işleme
|
||||
|
||||
#### Depolama Türüne Göre Koleksiyon Durumu Takibi
|
||||
|
||||
Her depolama arka ucu, yeteneklerine bağlı olarak koleksiyon durumunu farklı şekilde takip eder:
|
||||
|
||||
**Cassandra Üçlü Deposu:**
|
||||
Mevcut `triples_collection` tablosunu kullanır
|
||||
Koleksiyon oluşturulduğunda sistem işaretleyici üçlüsü oluşturur
|
||||
Sorgu: `SELECT collection FROM triples_collection WHERE collection = ? LIMIT 1`
|
||||
Koleksiyonun varlığı için verimli tek bölüm kontrolü
|
||||
|
||||
**Qdrant/Milvus/Pinecone Vektör Depoları:**
|
||||
Yerel koleksiyon API'leri, varlık kontrolü sağlar
|
||||
Koleksiyonlar, uygun vektör yapılandırmasıyla oluşturulur
|
||||
`collection_exists()` yöntemi, depolama API'sini kullanır
|
||||
Koleksiyon oluşturma, boyut gereksinimlerini doğrular
|
||||
|
||||
**Neo4j/Memgraph/FalkorDB Grafik Depoları:**
|
||||
Koleksiyonları takip etmek için `:CollectionMetadata` düğümlerini kullanır
|
||||
Düğüm özellikleri: `{user, collection, created_at}`
|
||||
Sorgu: `MATCH (c:CollectionMetadata {user: $user, collection: $collection})`
|
||||
Veri düğümlerinden ayrı olarak, temiz bir ayrım sağlar
|
||||
Koleksiyon listeleme ve doğrulama için verimli bir yol sağlar
|
||||
|
||||
**Cassandra Nesne Deposu:**
|
||||
Koleksiyon meta veri tablosunu veya işaretçi satırlarını kullanır
|
||||
Üçlü depoya benzer bir desen
|
||||
Veri yazmadan önce koleksiyonu doğrular
|
||||
|
||||
### API'ler
|
||||
|
||||
Koleksiyon Yönetimi API'leri (Kütüphaneci):
|
||||
**Koleksiyon Oluşturma/Güncelleme**: Yeni bir koleksiyon oluşturma veya mevcut meta verileri `tg-set-collection` aracılığıyla güncelleme
|
||||
**Koleksiyonları Listeleme**: İsteğe bağlı etiket filtrelemesiyle bir kullanıcı için koleksiyonları alma
|
||||
**Koleksiyon Silme**: Koleksiyonu ve ilişkili verileri silme, tüm mağaza türlerine kadar yayılma
|
||||
|
||||
Depolama Yönetimi API'leri (Tüm Depolama İşlemcileri):
|
||||
**Koleksiyon Oluşturma**: "koleksiyon oluştur" işlemini işleme, depolamada koleksiyonu oluşturma
|
||||
**Koleksiyon Silme**: "koleksiyon sil" işlemini işleme, tüm koleksiyon verilerini silme
|
||||
**Koleksiyon Varlığı Kontrolü**: Yazma işlemlerini kabul etmeden önce iç doğrulama
|
||||
|
||||
Veri İşlemleri API'leri (Değiştirilmiş Davranış):
|
||||
**Yazma API'leri**: Veriyi kabul etmeden önce koleksiyonun varlığını doğrulama, mevcut değilse hata döndürme
|
||||
**Sorgu API'leri**: Hata olmadan mevcut olmayan koleksiyonlar için boş sonuçlar döndürme
|
||||
|
||||
### Uygulama Ayrıntıları
|
||||
|
||||
Uygulama, hizmet entegrasyonu ve CLI komut yapısı için mevcut TrustGraph desenlerini takip edecektir.
|
||||
|
||||
#### Koleksiyon Silme Yayılımı
|
||||
|
||||
Bir kullanıcı, kütüphaneci hizmeti aracılığıyla koleksiyon silme işlemini başlattığında:
|
||||
|
||||
1. **Meta Veri Doğrulama**: Koleksiyonun var olduğunu ve kullanıcının silme izni olup olmadığını doğrulayın
|
||||
2. **Depolama Yayılımı**: Kütüphaneci, tüm depolama yazıcıları arasında silme işlemini koordine eder:
|
||||
Vektör depolama yazıcısı: Kullanıcı ve koleksiyon için gömülmeleri ve vektör indekslerini kaldırır
|
||||
Nesne depolama yazıcısı: Kullanıcı ve koleksiyon için belgeleri ve dosyaları kaldırır
|
||||
Üçlü depolama yazıcısı: Kullanıcı ve koleksiyon için grafik verilerini ve üçlüleri kaldırır
|
||||
3. **Meta Veri Temizleme**: Cassandra'dan koleksiyon meta veri kaydını kaldırır
|
||||
4. **Hata İşleme**: Herhangi bir depolama silme işlemi başarısız olursa, geri alma veya yeniden deneme mekanizmaları aracılığıyla tutarlılığı koruyun
|
||||
|
||||
#### Koleksiyon Yönetimi Arayüzü
|
||||
|
||||
**⚠️ ESKİ YAKLAŞIM - YAPILANDIRMA TEMELLİ DESENE DEĞİŞTİRİLDİ**
|
||||
|
||||
Aşağıda açıklanan kuyruk tabanlı mimari, `CollectionConfigHandler` kullanarak bir yapılandırma tabanlı yaklaşımla değiştirilmiştir. Tüm depolama arka uçları artık özel yönetim kuyrukları yerine yapılandırma itme mesajları aracılığıyla koleksiyon güncellemeleri alır.
|
||||
|
||||
~~Tüm depolama yazıcıları, ortak bir şemaya sahip standart bir koleksiyon yönetimi arayüzü uygular:~~
|
||||
|
||||
~~**Mesaj Şeması (`StorageManagementRequest`):**~~
|
||||
```json
|
||||
{
|
||||
"operation": "create-collection" | "delete-collection",
|
||||
"user": "user123",
|
||||
"collection": "documents-2024"
|
||||
}
|
||||
```
|
||||
|
||||
~~**Sıra Mimarisi:**~~
|
||||
~~**Vektör Depolama Yönetimi Kuyruğu** (`vector-storage-management`): Vektör/gömme depoları~~
|
||||
~~**Nesne Depolama Yönetimi Kuyruğu** (`object-storage-management`): Nesne/belge depoları~~
|
||||
~~**Üçlü Depolama Yönetimi Kuyruğu** (`triples-storage-management`): Grafik/RDF depoları~~
|
||||
~~**Depolama Yanıt Kuyruğu** (`storage-management-response`): Tüm yanıtlar buraya gönderilir~~
|
||||
|
||||
**Mevcut Uygulama:**
|
||||
|
||||
Tüm depolama arka uçları artık `CollectionConfigHandler` kullanır:
|
||||
**Yapılandırma İtme Entegrasyonu**: Depolama hizmetleri, yapılandırma itme bildirimleri için kayıt yaptırır
|
||||
**Otomatik Senkronizasyon**: Koleksiyonlar, yapılandırma değişikliklerine göre oluşturulur/silinir
|
||||
**Bildirimsel Model**: Koleksiyonlar, yapılandırma hizmetinde tanımlanır, arka uçlar eşleşmesi için senkronize olur
|
||||
**İstek/Yanıt Yok**: Koordinasyon yükünü ve yanıt takibini ortadan kaldırır
|
||||
**Koleksiyon Durumu Takibi**: `known_collections` önbelleği aracılığıyla sürdürülür
|
||||
**İdeolojik İşlemler**: Aynı yapılandırmayı birden çok kez işlemek güvenlidir
|
||||
|
||||
Her depolama arka ucu şunları uygular:
|
||||
`create_collection(user: str, collection: str, metadata: dict)` - Koleksiyon yapılarını oluşturur
|
||||
`delete_collection(user: str, collection: str)` - Tüm koleksiyon verilerini kaldırır
|
||||
`collection_exists(user: str, collection: str) -> bool` - Yazmadan önce doğrular
|
||||
|
||||
#### Cassandra Üçlü Depolama Yeniden Düzenlemesi
|
||||
|
||||
Bu uygulamanın bir parçası olarak, Cassandra üçlü depolama, bir koleksiyon başına tablo modelinden tek bir tablo modeline yeniden düzenlenecektir:
|
||||
|
||||
**Mevcut Mimari:**
|
||||
Kullanıcı başına bir anahtar alanı, her koleksiyon için ayrı bir tablo
|
||||
Şema: `(s, p, o)` ile `PRIMARY KEY (s, p, o)`
|
||||
Tablo adları: Kullanıcı koleksiyonları, ayrı Cassandra tabloları haline gelir
|
||||
|
||||
**Yeni Mimari:**
|
||||
Kullanıcı başına bir anahtar alanı, tüm koleksiyonlar için tek bir "üçlüler" tablosu
|
||||
Şema: `(collection, s, p, o)` ile `PRIMARY KEY (collection, s, p, o)`
|
||||
Koleksiyon izolasyonu, koleksiyon bölümlendirmesi yoluyla sağlanır
|
||||
|
||||
**Gerekli Değişiklikler:**
|
||||
|
||||
1. **TrustGraph Sınıfı Yeniden Düzenlemesi** (`trustgraph/direct/cassandra.py`):
|
||||
Oluşturucudan `table` parametresini kaldırın, sabit "üçlüler" tablosunu kullanın
|
||||
Tüm yöntemlere `collection` parametresini ekleyin
|
||||
Koleksiyonu ilk sütun olarak içeren şemayı güncelleyin
|
||||
**Dizin Güncellemeleri**: Tüm 8 sorgu desenini desteklemek için yeni dizinler oluşturulacaktır:
|
||||
`(s)` üzerine dizin, konu tabanlı sorgular için
|
||||
`(p)` üzerine dizin, öznelik tabanlı sorgular için
|
||||
`(o)` üzerine dizin, nesne tabanlı sorgular için
|
||||
Not: Cassandra, çok sütunlu ikincil dizinleri desteklemez, bu nedenle bunlar tek sütunlu dizinlerdir
|
||||
|
||||
**Sorgu Deseni Performansı:**
|
||||
✅ `get_all()` - `collection` üzerinde bölüm taraması
|
||||
✅ `get_s(s)` - birincil anahtarı verimli kullanır (`collection, s`)
|
||||
✅ `get_p(p)` - `idx_p` ile `collection` filtrelemesini kullanır
|
||||
✅ `get_o(o)` - `idx_o` ile `collection` filtrelemesini kullanır
|
||||
✅ `get_sp(s, p)` - birincil anahtarı verimli kullanır (`collection, s, p`)
|
||||
⚠️ `get_po(p, o)` - `ALLOW FILTERING` gerektirir (ya `idx_p` veya `idx_o` artı filtreleme kullanır)
|
||||
✅ `get_os(o, s)` - `idx_o` ile ek filtreleme `s` üzerinde kullanır
|
||||
✅ `get_spo(s, p, o)` - tüm birincil anahtarı verimli kullanır
|
||||
|
||||
**ALLOW FILTERING Notu:** `get_po` sorgu deseni, uygun bir birleşik dizin olmadan hem öznitelik hem de nesne kısıtlamalarına ihtiyaç duyduğu için `ALLOW FILTERING` gerektirir. Bu kabul edilebilir çünkü bu sorgu deseni, tipik üçlü depolama kullanımında konu tabanlı sorgulara göre daha az yaygındır
|
||||
|
||||
2. **Depolama Yazarı Güncellemeleri** (`trustgraph/storage/triples/cassandra/write.py`):
|
||||
(kullanıcı, koleksiyon) başına bir bağlantı yerine, kullanıcı başına tek bir TrustGraph bağlantısı sürdürün
|
||||
Ekleme işlemlerine koleksiyonu iletin
|
||||
Daha az bağlantıyla daha verimli kaynak kullanımı
|
||||
|
||||
3. **Sorgu Hizmeti Güncellemeleri** (`trustgraph/query/triples/cassandra/service.py`):
|
||||
Kullanıcı başına tek bir TrustGraph bağlantısı
|
||||
Tüm sorgu işlemlerine koleksiyonu iletin
|
||||
Koleksiyon parametresiyle aynı sorgu mantığını koruyun
|
||||
|
||||
**Faydaları:**
|
||||
**Basitleştirilmiş Koleksiyon Silme:** Tüm 4 tablo üzerinde `collection` bölüm anahtarını kullanarak silme
|
||||
**Kaynak Verimliliği:** Daha az veritabanı bağlantısı ve tablo nesnesi
|
||||
**Çoklu Koleksiyon İşlemleri:** Birden çok koleksiyonu kapsayan işlemleri uygulamak daha kolaydır
|
||||
**Tutarlı Mimari:** Birleşik koleksiyon meta veri yaklaşımıyla uyumludur
|
||||
**Koleksiyon Doğrulama:** `triples_collection` tablosu aracılığıyla koleksiyonun varlığını kontrol etmek kolaydır
|
||||
|
||||
Koleksiyon işlemleri, mümkün olduğunda atomik olacak ve uygun hata yönetimi ve doğrulama sağlayacaktır.
|
||||
|
||||
## Güvenlik Hususları
|
||||
|
||||
Koleksiyon yönetimi işlemleri, yetkisiz erişimi veya koleksiyonların silinmesini önlemek için uygun yetkilendirme gerektirir. Erişim kontrolü, mevcut TrustGraph güvenlik modelleriyle uyumlu olacaktır.
|
||||
|
||||
## Performans Hususları
|
||||
|
||||
Koleksiyon listeleme işlemleri, çok sayıda koleksiyon içeren ortamlarda sayfalama gerektirebilir. Meta veri sorguları, yaygın filtreleme kalıpları için optimize edilmelidir.
|
||||
|
||||
## Test Stratejisi
|
||||
|
||||
Kapsamlı testler şunları kapsayacaktır:
|
||||
Koleksiyon oluşturma iş akışı, uçtan uca
|
||||
Depolama arka uç senkronizasyonu
|
||||
Var olmayan koleksiyonlar için yazma doğrulaması
|
||||
Var olmayan koleksiyonların sorgu işlenmesi
|
||||
Koleksiyon silme işleminin tüm depolama alanlarında yayılması
|
||||
Hata yönetimi ve kurtarma senaryoları
|
||||
Her depolama arka ucu için birim testleri
|
||||
Çapraz depolama işlemleri için entegrasyon testleri
|
||||
|
||||
## Uygulama Durumu
|
||||
|
||||
### ✅ Tamamlanmış Bileşenler
|
||||
|
||||
1. **Librarian Koleksiyon Yönetimi Hizmeti** (`trustgraph-flow/trustgraph/librarian/collection_manager.py`)
|
||||
Koleksiyon meta veri CRUD işlemleri (listeleme, güncelleme, silme)
|
||||
`LibraryTableStore` aracılığıyla Cassandra koleksiyon meta veri tablosu entegrasyonu
|
||||
Koleksiyon silme işleminin tüm depolama türleri arasında koordinasyonu
|
||||
Uygun hata yönetimi ile asenkron istek/yanıt işleme
|
||||
|
||||
2. **Koleksiyon Meta Veri Şeması** (`trustgraph-base/trustgraph/schema/services/collection.py`)
|
||||
`CollectionManagementRequest` ve `CollectionManagementResponse` şemaları
|
||||
Koleksiyon kayıtları için `CollectionMetadata` şeması
|
||||
Koleksiyon istek/yanıt kuyruğu konu tanımları
|
||||
|
||||
3. **Depolama Yönetimi Şeması** (`trustgraph-base/trustgraph/schema/services/storage.py`)
|
||||
`StorageManagementRequest` ve `StorageManagementResponse` şemaları
|
||||
Depolama yönetimi kuyruğu konuları tanımlandı
|
||||
Depolama seviyesindeki koleksiyon işlemleri için mesaj formatı
|
||||
|
||||
4. **Cassandra 4-Tablo Şeması** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py`)
|
||||
Sorgu performansı için birleşik bölüm anahtarları
|
||||
SPO sorguları ve silme takibi için `triples_collection` tablosu
|
||||
Koleksiyon silme işlemi, okuyup sonra silme kalıbıyla uygulandı
|
||||
|
||||
### ✅ Yapılandırma Tabanlı Kalıba Geçiş - TAMAMLANDI
|
||||
|
||||
**Tüm depolama arka uçları, kuyruk tabanlı kalıptan yapılandırma tabanlı `CollectionConfigHandler` kalıbına geçirildi.**
|
||||
|
||||
Tamamlanan geçişler:
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/neo4j/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/memgraph/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/falkordb/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
|
||||
Tüm arka uçlar artık:
|
||||
`CollectionConfigHandler`'dan miras almaktadır
|
||||
`self.register_config_handler(self.on_collection_config)` aracılığıyla yapılandırma itme bildirimleri için kayıtlıdır
|
||||
`create_collection(user, collection, metadata)` ve `delete_collection(user, collection)`'i uygulamaktadır
|
||||
Yazmadan önce `collection_exists(user, collection)` ile doğrulamaktadır
|
||||
Otomatik olarak yapılandırma hizmeti değişiklikleriyle senkronize olmaktadır
|
||||
|
||||
Eski kuyruk tabanlı altyapı kaldırıldı:
|
||||
✅ `StorageManagementRequest` ve `StorageManagementResponse` şemaları kaldırıldı
|
||||
✅ Depolama yönetimi kuyruğu konu tanımları kaldırıldı
|
||||
✅ Tüm arka uçlardan depolama yönetimi tüketici/üretici kaldırıldı
|
||||
✅ Tüm arka uçlardan `on_storage_management` işleyicileri kaldırıldı
|
||||
410
docs/tech-specs/collection-management.zh-cn.md
Normal file
410
docs/tech-specs/collection-management.zh-cn.md
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Collection Management Technical Specification"
|
||||
parent: "Chinese (Beta)"
|
||||
---
|
||||
|
||||
# Collection Management Technical Specification
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Overview
|
||||
|
||||
本规范描述了 TrustGraph 的集合管理功能,要求显式创建集合,并提供对集合生命周期的直接控制。在开始使用之前,必须显式创建集合,以确保 librarian 元数据与所有存储后端之间的正确同步。该功能支持四个主要用例:
|
||||
|
||||
1. **集合创建 (Collection Creation)**: 在存储数据之前,显式创建集合。
|
||||
2. **集合列表 (Collection Listing)**: 查看系统中所有现有的集合。
|
||||
3. **集合元数据管理 (Collection Metadata Management)**: 更新集合的名称、描述和标签。
|
||||
4. **集合删除 (Collection Deletion)**: 删除集合及其关联的数据,包括所有存储类型。
|
||||
|
||||
## Goals
|
||||
|
||||
**显式集合创建 (Explicit Collection Creation)**: 要求在存储数据之前创建集合。
|
||||
**存储同步 (Storage Synchronization)**: 确保集合存在于所有存储后端(向量、对象、三元组)中。
|
||||
**集合可见性 (Collection Visibility)**: 允许用户列出并检查其环境中的所有集合。
|
||||
**集合清理 (Collection Cleanup)**: 允许删除不再需要的集合。
|
||||
**集合组织 (Collection Organization)**: 支持标签和标记,以便更好地跟踪和发现集合。
|
||||
**元数据管理 (Metadata Management)**: 为集合关联有意义的元数据,以提高操作的清晰度。
|
||||
**集合发现 (Collection Discovery)**: 通过过滤和搜索,更容易找到特定的集合。
|
||||
**操作透明性 (Operational Transparency)**: 提供对集合生命周期和使用的清晰可见性。
|
||||
**资源管理 (Resource Management)**: 允许清理未使用的集合,以优化资源利用率。
|
||||
**数据完整性 (Data Integrity)**: 阻止在存储中出现没有元数据跟踪的孤立集合。
|
||||
|
||||
## Background
|
||||
|
||||
以前,TrustGraph 中的集合是在数据加载操作期间隐式创建的,这会导致同步问题,即集合可能存在于存储后端中,但 librarian 中没有相应的元数据。这带来了管理挑战和潜在的数据孤立问题。
|
||||
|
||||
显式集合创建模型通过以下方式解决了这些问题:
|
||||
通过 `tg-set-collection` 要求在开始使用之前创建集合。
|
||||
将集合创建广播到所有存储后端。
|
||||
维护 librarian 元数据和存储之间的同步状态。
|
||||
阻止写入不存在的集合。
|
||||
提供清晰的集合生命周期管理。
|
||||
|
||||
本规范定义了显式集合管理模型。通过要求显式创建集合,TrustGraph 确保:
|
||||
集合从创建开始就在 librarian 元数据中进行跟踪。
|
||||
在接收数据之前,所有存储后端都了解集合。
|
||||
存储中不存在孤立的集合。
|
||||
对集合生命周期具有清晰的操作可见性和控制。
|
||||
当操作引用不存在的集合时,提供一致的错误处理。
|
||||
|
||||
## Technical Design
|
||||
|
||||
### Architecture
|
||||
|
||||
集合管理系统将实现于现有的 TrustGraph 基础设施中:
|
||||
|
||||
1. **Librarian Service Integration**
|
||||
集合管理操作将被添加到现有的 librarian 服务中。
|
||||
不需要新的服务 - 利用现有的身份验证和访问模式。
|
||||
处理集合列表、删除和元数据管理。
|
||||
|
||||
模块: trustgraph-librarian
|
||||
|
||||
2. **Cassandra Collection Metadata Table**
|
||||
在现有的 librarian keyspace 中创建一个新的表。
|
||||
存储具有用户范围访问权限的集合元数据。
|
||||
主键:(user_id, collection_id),用于适当的多租户支持。
|
||||
|
||||
模块: trustgraph-librarian
|
||||
|
||||
3. **Collection Management CLI**
|
||||
用于集合操作的命令行界面。
|
||||
提供列表、删除、标签和标记管理命令。
|
||||
与现有的 CLI 框架集成。
|
||||
|
||||
模块: trustgraph-cli
|
||||
|
||||
### Data Models
|
||||
|
||||
#### Cassandra Collection Metadata Table
|
||||
|
||||
集合元数据将存储在 librarian keyspace 中的结构化 Cassandra 表中:
|
||||
|
||||
```sql
|
||||
CREATE TABLE collections (
|
||||
user text,
|
||||
collection text,
|
||||
name text,
|
||||
description text,
|
||||
tags set<text>,
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
PRIMARY KEY (user, collection)
|
||||
);
|
||||
```
|
||||
|
||||
表结构:
|
||||
**user** + **collection**: 复合主键,确保用户隔离
|
||||
**name**: 人类可读的集合名称
|
||||
**description**: 集合用途的详细描述
|
||||
**tags**: 用于分类和过滤的标签集合
|
||||
**created_at**: 集合创建时间戳
|
||||
**updated_at**: 最后修改时间戳
|
||||
|
||||
此方法允许:
|
||||
多租户集合管理,具有用户隔离
|
||||
通过用户和集合进行高效查询
|
||||
灵活的标签系统,用于组织
|
||||
生命周期跟踪,用于运营洞察
|
||||
|
||||
#### 集合生命周期
|
||||
|
||||
在进行任何数据操作之前,必须在 librarian 中显式创建集合:
|
||||
|
||||
1. **集合创建** (两种路径):
|
||||
|
||||
**路径 A: 用户发起创建** 通过 `tg-set-collection`:
|
||||
用户提供集合 ID、名称、描述和标签
|
||||
Librarian 在 `collections` 表中创建元数据记录
|
||||
Librarian 向所有存储后端广播 "create-collection"
|
||||
所有存储处理器创建集合并确认成功
|
||||
集合现在可以用于数据操作
|
||||
|
||||
**路径 B: 在文档提交时自动创建**:
|
||||
用户提交指定集合 ID 的文档
|
||||
Librarian 检查集合是否存在于元数据表中
|
||||
如果不存在: Librarian 使用默认值创建元数据 (name=collection_id, 描述/标签为空)
|
||||
Librarian 向所有存储后端广播 "create-collection"
|
||||
所有存储处理器创建集合并确认成功
|
||||
文档处理继续,此时集合已建立
|
||||
|
||||
两种路径都确保集合存在于 librarian 元数据中,并且所有存储后端都已同步,然后再允许进行数据操作。
|
||||
|
||||
2. **存储验证**: 写入操作验证集合是否存在:
|
||||
存储处理器在接受写入操作之前检查集合状态
|
||||
写入不存在的集合会返回错误
|
||||
这可以防止直接写入绕过 librarian 的集合创建逻辑
|
||||
|
||||
3. **查询行为**: 查询操作可以优雅地处理不存在的集合:
|
||||
查询不存在的集合会返回空结果
|
||||
不会为查询操作抛出错误
|
||||
允许探索,而无需集合存在
|
||||
|
||||
4. **元数据更新**: 用户可以在创建后更新集合元数据:
|
||||
通过 `tg-set-collection` 更新名称、描述和标签
|
||||
更新仅应用于 librarian 元数据
|
||||
存储后端保留集合,但元数据更新不会传播
|
||||
|
||||
5. **显式删除**: 用户通过 `tg-delete-collection` 删除集合:
|
||||
Librarian 向所有存储后端广播 "delete-collection"
|
||||
等待来自所有存储处理器的确认
|
||||
仅在存储清理完成后删除 librarian 元数据记录
|
||||
确保存储中没有孤立数据
|
||||
|
||||
**关键原则**: librarian 是集合创建的唯一控制点。 无论是通过用户命令还是文档提交发起,librarian 都会确保在允许进行数据操作之前,正确跟踪元数据并与存储后端同步。
|
||||
|
||||
需要的操作:
|
||||
**创建集合**: 通过 `tg-set-collection` 进行用户操作,或在文档提交时自动进行
|
||||
**更新集合元数据**: 用户操作,用于修改名称、描述和标签
|
||||
**删除集合**: 用户操作,用于删除集合及其数据,删除所有存储中的数据
|
||||
**列出集合**: 用户操作,用于查看带有标签过滤的集合
|
||||
|
||||
#### 多存储集合管理
|
||||
|
||||
集合存在于 TrustGraph 中的多个存储后端中:
|
||||
**向量存储** (Qdrant, Milvus, Pinecone): 存储嵌入和向量数据
|
||||
**对象存储** (Cassandra): 存储文档和文件数据
|
||||
**三元存储** (Cassandra, Neo4j, Memgraph, FalkorDB): 存储图/RDF 数据
|
||||
|
||||
Each store type implements:
|
||||
**Collection State Tracking**: Maintain knowledge of which collections exist
|
||||
**Collection Creation**: Accept and process "create-collection" operations
|
||||
**Collection Validation**: Check collection exists before accepting writes
|
||||
**Collection Deletion**: Remove all data for specified collection
|
||||
|
||||
The librarian service coordinates collection operations across all store types, ensuring:
|
||||
Collections created in all backends before use
|
||||
All backends confirm creation before returning success
|
||||
Synchronized collection lifecycle across storage types
|
||||
Consistent error handling when collections don't exist
|
||||
|
||||
#### Collection State Tracking by Storage Type
|
||||
|
||||
Each storage backend tracks collection state differently based on its capabilities:
|
||||
|
||||
**Cassandra Triple Store:**
|
||||
Uses existing `triples_collection` table
|
||||
Creates system marker triple when collection created
|
||||
Query: `SELECT collection FROM triples_collection WHERE collection = ? LIMIT 1`
|
||||
Efficient single-partition check for collection existence
|
||||
|
||||
**Qdrant/Milvus/Pinecone Vector Stores:**
|
||||
Native collection APIs provide existence checking
|
||||
Collections created with proper vector configuration
|
||||
`collection_exists()` method uses storage API
|
||||
Collection creation validates dimension requirements
|
||||
|
||||
**Neo4j/Memgraph/FalkorDB Graph Stores:**
|
||||
Use `:CollectionMetadata` nodes to track collections
|
||||
Node properties: `{user, collection, created_at}`
|
||||
Query: `MATCH (c:CollectionMetadata {user: $user, collection: $collection})`
|
||||
Separate from data nodes for clean separation
|
||||
Enables efficient collection listing and validation
|
||||
|
||||
**Cassandra Object Store:**
|
||||
Uses collection metadata table or marker rows
|
||||
Similar pattern to triple store
|
||||
Validates collection before document writes
|
||||
|
||||
### APIs
|
||||
|
||||
Collection Management APIs (Librarian):
|
||||
**Create/Update Collection**: Create new collection or update existing metadata via `tg-set-collection`
|
||||
**List Collections**: Retrieve collections for a user with optional tag filtering
|
||||
**Delete Collection**: Remove collection and associated data, cascading to all store types
|
||||
|
||||
Storage Management APIs (All Storage Processors):
|
||||
**Create Collection**: Handle "create-collection" operation, establish collection in storage
|
||||
**Delete Collection**: Handle "delete-collection" operation, remove all collection data
|
||||
**Collection Exists Check**: Internal validation before accepting write operations
|
||||
|
||||
Data Operation APIs (Modified Behavior):
|
||||
**Write APIs**: Validate collection exists before accepting data, return error if not
|
||||
**Query APIs**: Return empty results for non-existent collections without error
|
||||
|
||||
### Implementation Details
|
||||
|
||||
The implementation will follow existing TrustGraph patterns for service integration and CLI command structure.
|
||||
|
||||
#### Collection Deletion Cascade
|
||||
|
||||
When a user initiates collection deletion through the librarian service:
|
||||
|
||||
1. **Metadata Validation**: Verify collection exists and user has permission to delete
|
||||
2. **Store Cascade**: Librarian coordinates deletion across all store writers:
|
||||
Vector store writer: Remove embeddings and vector indexes for the user and collection
|
||||
Object store writer: Remove documents and files for the user and collection
|
||||
Triple store writer: Remove graph data and triples for the user and collection
|
||||
3. **Metadata Cleanup**: Remove collection metadata record from Cassandra
|
||||
4. **Error Handling**: If any store deletion fails, maintain consistency through rollback or retry mechanisms
|
||||
|
||||
#### Collection Management Interface
|
||||
|
||||
**⚠️ LEGACY APPROACH - REPLACED BY CONFIG-BASED PATTERN**
|
||||
|
||||
The queue-based architecture described below has been replaced with a config-based approach using `CollectionConfigHandler`. All storage backends now receive collection updates via config push messages instead of dedicated management queues.
|
||||
|
||||
~~All store writers implement a standardized collection management interface with a common schema:~~
|
||||
|
||||
~~**Message Schema (`StorageManagementRequest`):**~~
|
||||
```json
|
||||
{
|
||||
"operation": "create-collection" | "delete-collection",
|
||||
"user": "user123",
|
||||
"collection": "documents-2024"
|
||||
}
|
||||
```
|
||||
|
||||
~~**队列架构:**~~
|
||||
~~**向量存储管理队列** (`vector-storage-management`): 向量/嵌入式存储~~
|
||||
~~**对象存储管理队列** (`object-storage-management`): 对象/文档存储~~
|
||||
~~**三元组存储管理队列** (`triples-storage-management`): 图/RDF 存储~~
|
||||
~~**存储响应队列** (`storage-management-response`): 所有响应都发送到此处~~
|
||||
|
||||
**当前实现:**
|
||||
|
||||
所有存储后端现在都使用 `CollectionConfigHandler`:
|
||||
**配置推送集成**: 存储服务注册以接收配置推送通知
|
||||
**自动同步**: 基于配置更改创建/删除集合
|
||||
**声明式模型**: 集合在配置服务中定义,后端同步以匹配
|
||||
**无请求/响应**: 消除协调开销和响应跟踪
|
||||
**集合状态跟踪**: 通过 `known_collections` 缓存维护
|
||||
**幂等操作**: 安全地多次处理相同的配置
|
||||
|
||||
每个存储后端实现:
|
||||
`create_collection(user: str, collection: str, metadata: dict)` - 创建集合结构
|
||||
`delete_collection(user: str, collection: str)` - 移除所有集合数据
|
||||
`collection_exists(user: str, collection: str) -> bool` - 在写入之前进行验证
|
||||
|
||||
#### Cassandra 三元组存储重构
|
||||
|
||||
作为此实现的组成部分,Cassandra 三元组存储将从每个集合一个表的模型重构为统一的表模型:
|
||||
|
||||
**当前架构:**
|
||||
每个用户的键空间,每个集合的单独表
|
||||
模式:`(s, p, o)` with `PRIMARY KEY (s, p, o)`
|
||||
表名:用户集合成为单独的 Cassandra 表
|
||||
|
||||
**新的架构:**
|
||||
每个用户的键空间,用于所有集合的单个 "triples" 表
|
||||
模式:`(collection, s, p, o)` with `PRIMARY KEY (collection, s, p, o)`
|
||||
通过集合分区实现集合隔离
|
||||
|
||||
**需要更改的内容:**
|
||||
|
||||
1. **TrustGraph 类重构** (`trustgraph/direct/cassandra.py`):
|
||||
移除构造函数中的 `table` 参数,使用固定的 "triples" 表
|
||||
在所有方法中添加 `collection` 参数
|
||||
更新模式以包含集合作为第一列
|
||||
**索引更新**: 将创建新的索引以支持所有 8 个查询模式:
|
||||
在 `(s)` 上创建索引以进行基于主体的查询
|
||||
在 `(p)` 上创建索引以进行基于谓词的查询
|
||||
在 `(o)` 上创建索引以进行基于对象的查询
|
||||
注意:Cassandra 不支持多列二级索引,因此这些是单列索引
|
||||
|
||||
**查询模式性能:**
|
||||
✅ `get_all()` - 在 `collection` 上进行分区扫描
|
||||
✅ `get_s(s)` - 效率地使用主键 (`collection, s`)
|
||||
✅ `get_p(p)` - 使用 `idx_p` 并进行 `collection` 过滤
|
||||
✅ `get_o(o)` - 使用 `idx_o` 并进行 `collection` 过滤
|
||||
✅ `get_sp(s, p)` - 效率地使用主键 (`collection, s, p`)
|
||||
⚠️ `get_po(p, o)` - 需要 `ALLOW FILTERING` (使用 `idx_p` 或 `idx_o` 加上过滤)
|
||||
✅ `get_os(o, s)` - 使用 `idx_o` 并进行额外的 `s` 过滤
|
||||
✅ `get_spo(s, p, o)` - 效率地使用完整主键
|
||||
|
||||
**关于 ALLOW FILTERING 的说明**: `get_po` 查询模式需要 `ALLOW FILTERING`,因为它需要谓词和对象约束,而没有合适的复合索引。 这是一个可以接受的,因为此查询模式比在典型的三元组存储用例中基于主体的查询不太常见。
|
||||
|
||||
2. **存储写入器更新** (`trustgraph/storage/triples/cassandra/write.py`):
|
||||
维护每个用户单个 TrustGraph 连接,而不是每个 (用户, 集合)
|
||||
将集合传递给插入操作
|
||||
通过减少连接数提高资源利用率
|
||||
|
||||
3. **查询服务更新** (`trustgraph/query/triples/cassandra/service.py`):
|
||||
每个用户的单个 TrustGraph 连接
|
||||
将集合传递给所有查询操作
|
||||
保持相同的查询逻辑,并带有集合参数
|
||||
|
||||
**优点:**
|
||||
**简化集合删除**: 使用 `collection` 分区键删除所有 4 个表
|
||||
**资源效率**: 减少数据库连接和表对象
|
||||
**跨集合操作**: 更容易实现跨多个集合的操作
|
||||
**一致的架构**: 与统一的集合元数据方法保持一致
|
||||
**集合验证**: 可以通过 `triples_collection` 表轻松检查集合是否存在
|
||||
|
||||
集合操作在可能的情况下将是原子操作,并提供适当的错误处理和验证。
|
||||
|
||||
## 安全性考虑
|
||||
|
||||
集合管理操作需要适当的授权,以防止未经授权的访问或删除集合。 访问控制将与现有的 TrustGraph 安全模型保持一致。
|
||||
|
||||
## 性能考虑
|
||||
|
||||
集合列表操作可能需要分页,以适应具有大量集合的环境。 元数据查询应针对常见的过滤模式进行优化。
|
||||
|
||||
## 测试策略
|
||||
|
||||
综合测试将涵盖:
|
||||
集合创建工作流程的端到端流程
|
||||
存储后端同步
|
||||
对不存在集合的写入验证
|
||||
对不存在集合的查询处理
|
||||
集合删除在所有存储中的级联操作
|
||||
错误处理和恢复场景
|
||||
每个存储后端的单元测试
|
||||
跨存储操作的集成测试
|
||||
|
||||
## 实施状态
|
||||
|
||||
### ✅ 已完成的组件
|
||||
|
||||
1. **Librarian 集合管理服务** (`trustgraph-flow/trustgraph/librarian/collection_manager.py`)
|
||||
集合元数据 CRUD 操作(列表、更新、删除)
|
||||
通过 `LibraryTableStore` 与 Cassandra 集合元数据表集成
|
||||
集合删除在所有存储类型上的级联协调
|
||||
具有适当错误管理的异步请求/响应处理
|
||||
|
||||
2. **集合元数据模式** (`trustgraph-base/trustgraph/schema/services/collection.py`)
|
||||
`CollectionManagementRequest` 和 `CollectionManagementResponse` 模式
|
||||
`CollectionMetadata` 模式用于集合记录
|
||||
集合请求/响应队列主题定义
|
||||
|
||||
3. **存储管理模式** (`trustgraph-base/trustgraph/schema/services/storage.py`)
|
||||
`StorageManagementRequest` 和 `StorageManagementResponse` 模式
|
||||
定义了存储管理队列主题
|
||||
存储级别集合操作的消息格式
|
||||
|
||||
4. **Cassandra 4-表模式** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py`)
|
||||
用于查询性能的复合分区键
|
||||
`triples_collection` 表用于 SPO 查询和删除跟踪
|
||||
集合删除使用读后删除模式实现
|
||||
|
||||
### ✅ 迁移到基于配置的模式 - 已完成
|
||||
|
||||
**所有存储后端已从基于队列的模式迁移到基于配置的 `CollectionConfigHandler` 模式。**
|
||||
|
||||
已完成的迁移:
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/neo4j/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/memgraph/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/triples/falkordb/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py`
|
||||
✅ `trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
|
||||
所有后端现在:
|
||||
继承自 `CollectionConfigHandler`
|
||||
通过 `self.register_config_handler(self.on_collection_config)` 注册配置推送通知
|
||||
实施 `create_collection(user, collection, metadata)` 和 `delete_collection(user, collection)`
|
||||
使用 `collection_exists(user, collection)` 在写入之前进行验证
|
||||
自动与配置服务更改同步
|
||||
|
||||
移除了旧的基于队列的基础设施:
|
||||
✅ 移除了 `StorageManagementRequest` 和 `StorageManagementResponse` 模式
|
||||
✅ 移除了存储管理队列主题定义
|
||||
✅ 移除了所有后端中的存储管理生产者/消费者
|
||||
✅ 移除了所有后端中的 `on_storage_management` 处理程序
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Config Push 'Notify' Pattern Technical Specification"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Config Push "Notify" Pattern Technical Specification
|
||||
|
||||
## Overview
|
||||
|
|
|
|||
144
docs/tech-specs/document-embeddings-chunk-id.ar.md
Normal file
144
docs/tech-specs/document-embeddings-chunk-id.ar.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
layout: default
|
||||
title: "تضمينات المستندات - مُعرّف الجزء"
|
||||
parent: "Arabic (Beta)"
|
||||
---
|
||||
|
||||
# تضمينات المستندات - مُعرّف الجزء
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
تخزين تضمينات المستندات يخزن حاليًا نص الجزء مباشرةً في حمولة مخزن المتجهات، مما يكرر البيانات الموجودة في Garage. يحل هذا المخطط تخزين نص الجزء باستخدام مراجع `chunk_id`.
|
||||
|
||||
## الحالة الحالية
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk: bytes = b""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunks: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
حمولة تخزين المتجهات:
|
||||
```python
|
||||
payload={"doc": chunk} # Duplicates Garage content
|
||||
```
|
||||
|
||||
## التصميم
|
||||
|
||||
### تغييرات المخطط
|
||||
|
||||
**ChunkEmbeddings** - استبدال "chunk" بـ "chunk_id":
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk_id: str = ""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**DocumentEmbeddingsResponse** - إرجاع معرفات الأجزاء (chunk_ids) بدلاً من الأجزاء نفسها:
|
||||
```python
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunk_ids: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
### حمولة مستودع المتجهات
|
||||
|
||||
جميع المستودعات (Qdrant، Milvus، Pinecone):
|
||||
```python
|
||||
payload={"chunk_id": chunk_id}
|
||||
```
|
||||
|
||||
### التغييرات في معالج مستند RAG
|
||||
|
||||
يقوم معالج مستند RAG باسترداد محتوى الأجزاء من نظام Garage:
|
||||
|
||||
```python
|
||||
# Get chunk_ids from embeddings store
|
||||
chunk_ids = await self.rag.doc_embeddings_client.query(...)
|
||||
|
||||
# Fetch chunk content from Garage
|
||||
docs = []
|
||||
for chunk_id in chunk_ids:
|
||||
content = await self.rag.librarian_client.get_document_content(
|
||||
chunk_id, self.user
|
||||
)
|
||||
docs.append(content)
|
||||
```
|
||||
|
||||
### التغييرات في واجهة برمجة التطبيقات (API) / مجموعة تطوير البرمجيات (SDK)
|
||||
|
||||
**DocumentEmbeddingsClient** تُرجع `chunk_ids`:
|
||||
```python
|
||||
return resp.chunk_ids # Changed from resp.chunks
|
||||
```
|
||||
|
||||
**تنسيق البيانات** (DocumentEmbeddingsResponseTranslator):
|
||||
```python
|
||||
result["chunk_ids"] = obj.chunk_ids # Changed from chunks
|
||||
```
|
||||
|
||||
### تغييرات واجهة سطر الأوامر (CLI)
|
||||
|
||||
تعرض أداة واجهة سطر الأوامر (CLI) معرفات الأجزاء (يمكن للمستخدمين استرداد المحتوى بشكل منفصل إذا لزم الأمر).
|
||||
|
||||
## الملفات التي يجب تعديلها
|
||||
|
||||
### المخطط (Schema)
|
||||
`trustgraph-base/trustgraph/schema/knowledge/embeddings.py` - ChunkEmbeddings
|
||||
`trustgraph-base/trustgraph/schema/services/query.py` - DocumentEmbeddingsResponse
|
||||
|
||||
### الرسائل/المترجمات
|
||||
`trustgraph-base/trustgraph/messaging/translators/embeddings_query.py` - DocumentEmbeddingsResponseTranslator
|
||||
|
||||
### العميل (Client)
|
||||
`trustgraph-base/trustgraph/base/document_embeddings_client.py` - إرجاع معرفات الأجزاء
|
||||
|
||||
### حزمة تطوير البرمجيات (SDK) / واجهة برمجة التطبيقات (API) بلغة بايثون
|
||||
`trustgraph-base/trustgraph/api/flow.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/socket_client.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/async_flow.py` - إذا كان ذلك ممكنًا
|
||||
`trustgraph-base/trustgraph/api/bulk_client.py` - استيراد/تصدير تضمينات المستندات
|
||||
`trustgraph-base/trustgraph/api/async_bulk_client.py` - استيراد/تصدير تضمينات المستندات
|
||||
|
||||
### خدمة التضمينات
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py` - تمرير معرف الجزء
|
||||
|
||||
### أدوات الكتابة في التخزين
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
|
||||
### خدمات الاستعلام
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/milvus/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/pinecone/service.py`
|
||||
|
||||
### البوابة (Gateway)
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_query.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_export.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_import.py`
|
||||
|
||||
### استرجاع المعلومات من المستندات (Document RAG)
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` - إضافة عميل أمين المكتبة
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` - الاسترداد من Garage
|
||||
|
||||
### واجهة سطر الأوامر (CLI)
|
||||
`trustgraph-cli/trustgraph/cli/invoke_document_embeddings.py`
|
||||
`trustgraph-cli/trustgraph/cli/save_doc_embeds.py`
|
||||
`trustgraph-cli/trustgraph/cli/load_doc_embeds.py`
|
||||
|
||||
## الفوائد
|
||||
|
||||
1. مصدر واحد للحقيقة - نص الأجزاء فقط في Garage
|
||||
2. تقليل مساحة التخزين في مخزن المتجهات
|
||||
3. يتيح تتبع مصدر المعلومات في وقت الاستعلام عبر معرف الجزء.
|
||||
144
docs/tech-specs/document-embeddings-chunk-id.es.md
Normal file
144
docs/tech-specs/document-embeddings-chunk-id.es.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Identificador de fragmento de incrustaciones de documentos"
|
||||
parent: "Spanish (Beta)"
|
||||
---
|
||||
|
||||
# Identificador de fragmento de incrustaciones de documentos
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Resumen
|
||||
|
||||
Actualmente, el almacenamiento de incrustaciones de documentos almacena directamente el texto del fragmento en la carga útil de la base de datos vectorial, duplicando datos que existen en Garage. Esta especificación reemplaza el almacenamiento del texto del fragmento con referencias `chunk_id`.
|
||||
|
||||
## Estado actual
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk: bytes = b""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunks: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Carga útil del almacén de vectores:
|
||||
```python
|
||||
payload={"doc": chunk} # Duplicates Garage content
|
||||
```
|
||||
|
||||
## Diseño
|
||||
|
||||
### Cambios en el esquema
|
||||
|
||||
**ChunkEmbeddings** - reemplazar "chunk" con "chunk_id":
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk_id: str = ""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**DocumentEmbeddingsResponse** - devolver `chunk_ids` en lugar de `chunks`:
|
||||
```python
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunk_ids: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
### Carga útil del almacén de vectores
|
||||
|
||||
Todos los almacenes (Qdrant, Milvus, Pinecone):
|
||||
```python
|
||||
payload={"chunk_id": chunk_id}
|
||||
```
|
||||
|
||||
### Cambios en el Documento RAG
|
||||
|
||||
El procesador de documentos RAG recupera el contenido de los fragmentos de Garage:
|
||||
|
||||
```python
|
||||
# Get chunk_ids from embeddings store
|
||||
chunk_ids = await self.rag.doc_embeddings_client.query(...)
|
||||
|
||||
# Fetch chunk content from Garage
|
||||
docs = []
|
||||
for chunk_id in chunk_ids:
|
||||
content = await self.rag.librarian_client.get_document_content(
|
||||
chunk_id, self.user
|
||||
)
|
||||
docs.append(content)
|
||||
```
|
||||
|
||||
### Cambios en la API/SDK
|
||||
|
||||
**DocumentEmbeddingsClient** devuelve chunk_ids:
|
||||
```python
|
||||
return resp.chunk_ids # Changed from resp.chunks
|
||||
```
|
||||
|
||||
**Formato de cable** (DocumentEmbeddingsResponseTranslator):
|
||||
```python
|
||||
result["chunk_ids"] = obj.chunk_ids # Changed from chunks
|
||||
```
|
||||
|
||||
### Cambios en la CLI
|
||||
|
||||
La herramienta de la CLI muestra los chunk_ids (los usuarios pueden obtener el contenido por separado si es necesario).
|
||||
|
||||
## Archivos a Modificar
|
||||
|
||||
### Esquema
|
||||
`trustgraph-base/trustgraph/schema/knowledge/embeddings.py` - ChunkEmbeddings
|
||||
`trustgraph-base/trustgraph/schema/services/query.py` - DocumentEmbeddingsResponse
|
||||
|
||||
### Mensajería/Traductores
|
||||
`trustgraph-base/trustgraph/messaging/translators/embeddings_query.py` - DocumentEmbeddingsResponseTranslator
|
||||
|
||||
### Cliente
|
||||
`trustgraph-base/trustgraph/base/document_embeddings_client.py` - return chunk_ids
|
||||
|
||||
### SDK/API de Python
|
||||
`trustgraph-base/trustgraph/api/flow.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/socket_client.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/async_flow.py` - if applicable
|
||||
`trustgraph-base/trustgraph/api/bulk_client.py` - import/export document embeddings
|
||||
`trustgraph-base/trustgraph/api/async_bulk_client.py` - import/export document embeddings
|
||||
|
||||
### Servicio de Embeddings
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py` - pass chunk_id
|
||||
|
||||
### Escritores de Almacenamiento
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
|
||||
### Servicios de Consulta
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/milvus/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/pinecone/service.py`
|
||||
|
||||
### Gateway
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_query.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_export.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_import.py`
|
||||
|
||||
### Document RAG
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` - add librarian client
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` - fetch from Garage
|
||||
|
||||
### CLI
|
||||
`trustgraph-cli/trustgraph/cli/invoke_document_embeddings.py`
|
||||
`trustgraph-cli/trustgraph/cli/save_doc_embeds.py`
|
||||
`trustgraph-cli/trustgraph/cli/load_doc_embeds.py`
|
||||
|
||||
## Beneficios
|
||||
|
||||
1. Única fuente de verdad: solo el texto de los chunks en Garage.
|
||||
2. Almacenamiento de vectores reducido.
|
||||
3. Permite el rastreo de origen en tiempo de consulta a través del chunk_id.
|
||||
144
docs/tech-specs/document-embeddings-chunk-id.he.md
Normal file
144
docs/tech-specs/document-embeddings-chunk-id.he.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
layout: default
|
||||
title: "מזהה מקטע של הטמעות מסמכים"
|
||||
parent: "Hebrew (Beta)"
|
||||
---
|
||||
|
||||
# מזהה מקטע של הטמעות מסמכים
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## סקירה כללית
|
||||
|
||||
אחסון הטמעות מסמכים מאחסן כרגע את הטקסט של המקטעים ישירות בתוך מטען ה-vector store, מה שמשכפל נתונים הקיימים ב-Garage. מפרט זה מחליף את אחסון הטקסט של המקטעים עם הפניות ל-`chunk_id`.
|
||||
|
||||
## מצב נוכחי
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk: bytes = b""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunks: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
מטען אחסון וקטורים:
|
||||
```python
|
||||
payload={"doc": chunk} # Duplicates Garage content
|
||||
```
|
||||
|
||||
## עיצוב
|
||||
|
||||
### שינויים בסכימה
|
||||
|
||||
**ChunkEmbeddings** - החלפת "chunk" ב-"chunk_id":
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk_id: str = ""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**תגובת DocumentEmbeddingsResponse** - החזרת מזהי חלקים (chunk_ids) במקום חלקים (chunks):
|
||||
```python
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunk_ids: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
### מטען של אחסון וקטורים
|
||||
|
||||
כל האחסונים (Qdrant, Milvus, Pinecone):
|
||||
```python
|
||||
payload={"chunk_id": chunk_id}
|
||||
```
|
||||
|
||||
### שינויים במסמך RAG
|
||||
|
||||
מעבד מסמכי ה-RAG שולף תוכן מקטעים מ-Garage:
|
||||
|
||||
```python
|
||||
# Get chunk_ids from embeddings store
|
||||
chunk_ids = await self.rag.doc_embeddings_client.query(...)
|
||||
|
||||
# Fetch chunk content from Garage
|
||||
docs = []
|
||||
for chunk_id in chunk_ids:
|
||||
content = await self.rag.librarian_client.get_document_content(
|
||||
chunk_id, self.user
|
||||
)
|
||||
docs.append(content)
|
||||
```
|
||||
|
||||
### שינויים ב-API/SDK
|
||||
|
||||
**DocumentEmbeddingsClient** מחזיר את chunk_ids:
|
||||
```python
|
||||
return resp.chunk_ids # Changed from resp.chunks
|
||||
```
|
||||
|
||||
**פורמט של נתונים** (DocumentEmbeddingsResponseTranslator):
|
||||
```python
|
||||
result["chunk_ids"] = obj.chunk_ids # Changed from chunks
|
||||
```
|
||||
|
||||
### שינויים בממשק שורת הפקודה (CLI)
|
||||
|
||||
כלי ה-CLI מציג מזהי חלקים (chunk_ids) (המשתמשים יכולים לשלוף את התוכן בנפרד אם יש צורך).
|
||||
|
||||
## קבצים לשינוי
|
||||
|
||||
### סכימה (Schema)
|
||||
`trustgraph-base/trustgraph/schema/knowledge/embeddings.py` - ChunkEmbeddings
|
||||
`trustgraph-base/trustgraph/schema/services/query.py` - DocumentEmbeddingsResponse
|
||||
|
||||
### הודעות/מתרגמים
|
||||
`trustgraph-base/trustgraph/messaging/translators/embeddings_query.py` - DocumentEmbeddingsResponseTranslator
|
||||
|
||||
### לקוח (Client)
|
||||
`trustgraph-base/trustgraph/base/document_embeddings_client.py` - החזרת מזהי חלקים (chunk_ids)
|
||||
|
||||
### ערכת פיתוח תוכנה (SDK) / API בפייתון
|
||||
`trustgraph-base/trustgraph/api/flow.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/socket_client.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/async_flow.py` - אם רלוונטי
|
||||
`trustgraph-base/trustgraph/api/bulk_client.py` - ייבוא/ייצוא של הטמעות מסמכים (document embeddings)
|
||||
`trustgraph-base/trustgraph/api/async_bulk_client.py` - ייבוא/ייצוא של הטמעות מסמכים (document embeddings)
|
||||
|
||||
### שירות הטמעות
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py` - העברת מזהה חלק (chunk_id)
|
||||
|
||||
### כותבי אחסון
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
|
||||
### שירותי שאילתות
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/milvus/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/pinecone/service.py`
|
||||
|
||||
### שער (Gateway)
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_query.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_export.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_import.py`
|
||||
|
||||
### אחזור מידע ממסמכים (Document RAG)
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` - הוספת לקוח של "ספרן" (librarian)
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` - שליפה מ-"Garage"
|
||||
|
||||
### ממשק שורת הפקודה (CLI)
|
||||
`trustgraph-cli/trustgraph/cli/invoke_document_embeddings.py`
|
||||
`trustgraph-cli/trustgraph/cli/save_doc_embeds.py`
|
||||
`trustgraph-cli/trustgraph/cli/load_doc_embeds.py`
|
||||
|
||||
## יתרונות
|
||||
|
||||
1. מקור יחיד לאמת - טקסט החלקים נמצא רק ב-"Garage".
|
||||
2. הפחתת נפח האחסון של מאגר הווקטורים.
|
||||
3. מאפשר מעקב אחר מקור המידע בזמן השאילתה באמצעות מזהה החלק (chunk_id).
|
||||
144
docs/tech-specs/document-embeddings-chunk-id.hi.md
Normal file
144
docs/tech-specs/document-embeddings-chunk-id.hi.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
layout: default
|
||||
title: "दस्तावेज़ एम्बेडिंग चंक आईडी"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# दस्तावेज़ एम्बेडिंग चंक आईडी
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## अवलोकन
|
||||
|
||||
वर्तमान में, दस्तावेज़ एम्बेडिंग स्टोरेज चंक टेक्स्ट को सीधे वेक्टर स्टोर पेलोड में संग्रहीत करता है, जिससे गैरेज में मौजूद डेटा दोहराया जाता है। यह विनिर्देश चंक टेक्स्ट स्टोरेज को `chunk_id` संदर्भों से बदल देता है।
|
||||
|
||||
## वर्तमान स्थिति
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk: bytes = b""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunks: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
वेक्टर स्टोर पेलोड:
|
||||
```python
|
||||
payload={"doc": chunk} # Duplicates Garage content
|
||||
```
|
||||
|
||||
## डिज़ाइन
|
||||
|
||||
### स्कीमा में बदलाव
|
||||
|
||||
**ChunkEmbeddings** - "chunk" को "chunk_id" से बदलें:
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk_id: str = ""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**DocumentEmbeddingsResponse** - चंक्स के बजाय chunk_ids लौटाएं:
|
||||
```python
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunk_ids: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
### वेक्टर स्टोर पेलोड
|
||||
|
||||
सभी स्टोर (क्यूड्रेंट, मिल्वस, पाइनकोन):
|
||||
```python
|
||||
payload={"chunk_id": chunk_id}
|
||||
```
|
||||
|
||||
### दस्तावेज़ आरएजी (RAG) में बदलाव
|
||||
|
||||
दस्तावेज़ आरएजी प्रोसेसर, गराज (Garage) से चंक सामग्री प्राप्त करता है:
|
||||
|
||||
```python
|
||||
# Get chunk_ids from embeddings store
|
||||
chunk_ids = await self.rag.doc_embeddings_client.query(...)
|
||||
|
||||
# Fetch chunk content from Garage
|
||||
docs = []
|
||||
for chunk_id in chunk_ids:
|
||||
content = await self.rag.librarian_client.get_document_content(
|
||||
chunk_id, self.user
|
||||
)
|
||||
docs.append(content)
|
||||
```
|
||||
|
||||
### एपीआई/एसडीके में बदलाव
|
||||
|
||||
**DocumentEmbeddingsClient** चंक_आईडी (chunk_ids) लौटाता है:
|
||||
```python
|
||||
return resp.chunk_ids # Changed from resp.chunks
|
||||
```
|
||||
|
||||
**वायर प्रारूप** (DocumentEmbeddingsResponseTranslator):
|
||||
```python
|
||||
result["chunk_ids"] = obj.chunk_ids # Changed from chunks
|
||||
```
|
||||
|
||||
### CLI में बदलाव
|
||||
|
||||
CLI टूल `chunk_ids` प्रदर्शित करता है (उपयोगकर्ता आवश्यकता पड़ने पर सामग्री को अलग से प्राप्त कर सकते हैं)।
|
||||
|
||||
## संशोधित करने योग्य फाइलें
|
||||
|
||||
### स्कीमा
|
||||
`trustgraph-base/trustgraph/schema/knowledge/embeddings.py` - `ChunkEmbeddings`
|
||||
`trustgraph-base/trustgraph/schema/services/query.py` - `DocumentEmbeddingsResponse`
|
||||
|
||||
### मैसेजिंग/अनुवादक
|
||||
`trustgraph-base/trustgraph/messaging/translators/embeddings_query.py` - `DocumentEmbeddingsResponseTranslator`
|
||||
|
||||
### क्लाइंट
|
||||
`trustgraph-base/trustgraph/base/document_embeddings_client.py` - `chunk_ids` लौटाएं
|
||||
|
||||
### पायथन SDK/API
|
||||
`trustgraph-base/trustgraph/api/flow.py` - `document_embeddings_query`
|
||||
`trustgraph-base/trustgraph/api/socket_client.py` - `document_embeddings_query`
|
||||
`trustgraph-base/trustgraph/api/async_flow.py` - यदि लागू हो
|
||||
`trustgraph-base/trustgraph/api/bulk_client.py` - दस्तावेज़ एम्बेडिंग का आयात/निर्यात
|
||||
`trustgraph-base/trustgraph/api/async_bulk_client.py` - दस्तावेज़ एम्बेडिंग का आयात/निर्यात
|
||||
|
||||
### एम्बेडिंग सेवा
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py` - `chunk_id` पास करें
|
||||
|
||||
### स्टोरेज राइटर
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
|
||||
### क्वेरी सेवाएं
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/milvus/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/pinecone/service.py`
|
||||
|
||||
### गेटवे
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_query.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_export.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_import.py`
|
||||
|
||||
### दस्तावेज़ RAG
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` - लाइब्रेरियन क्लाइंट जोड़ें
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` - गैरेज से प्राप्त करें
|
||||
|
||||
### CLI
|
||||
`trustgraph-cli/trustgraph/cli/invoke_document_embeddings.py`
|
||||
`trustgraph-cli/trustgraph/cli/save_doc_embeds.py`
|
||||
`trustgraph-cli/trustgraph/cli/load_doc_embeds.py`
|
||||
|
||||
## लाभ
|
||||
|
||||
1. सत्य का एकल स्रोत - केवल गैरेज में टेक्स्ट चंक
|
||||
2. वेक्टर स्टोर स्टोरेज में कमी
|
||||
3. `chunk_id` के माध्यम से क्वेरी-टाइम उत्पत्ति को सक्षम करता है
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Document Embeddings Chunk ID"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Document Embeddings Chunk ID
|
||||
|
||||
## Overview
|
||||
|
|
|
|||
144
docs/tech-specs/document-embeddings-chunk-id.pt.md
Normal file
144
docs/tech-specs/document-embeddings-chunk-id.pt.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Incorporações de Documentos - ID do Trecho"
|
||||
parent: "Portuguese (Beta)"
|
||||
---
|
||||
|
||||
# Incorporações de Documentos - ID do Trecho
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Atualmente, o armazenamento de incorporações de documentos armazena o texto do trecho diretamente no payload do armazenamento vetorial, duplicando dados que já existem no Garage. Esta especificação substitui o armazenamento do texto do trecho por referências `chunk_id`.
|
||||
|
||||
## Estado Atual
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk: bytes = b""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunks: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Payload do armazenamento vetorial:
|
||||
```python
|
||||
payload={"doc": chunk} # Duplicates Garage content
|
||||
```
|
||||
|
||||
## Design
|
||||
|
||||
### Schema Changes
|
||||
|
||||
**ChunkEmbeddings** - substituir "chunk" por "chunk_id":
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk_id: str = ""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**DocumentEmbeddingsResponse** - retornar chunk_ids em vez de chunks:
|
||||
```python
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunk_ids: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
### Carga Útil do Armazenamento Vetorial
|
||||
|
||||
Todos os armazenamentos (Qdrant, Milvus, Pinecone):
|
||||
```python
|
||||
payload={"chunk_id": chunk_id}
|
||||
```
|
||||
|
||||
### Alterações no Processador de Documentos RAG
|
||||
|
||||
O processador de documentos RAG busca o conteúdo dos fragmentos do Garage:
|
||||
|
||||
```python
|
||||
# Get chunk_ids from embeddings store
|
||||
chunk_ids = await self.rag.doc_embeddings_client.query(...)
|
||||
|
||||
# Fetch chunk content from Garage
|
||||
docs = []
|
||||
for chunk_id in chunk_ids:
|
||||
content = await self.rag.librarian_client.get_document_content(
|
||||
chunk_id, self.user
|
||||
)
|
||||
docs.append(content)
|
||||
```
|
||||
|
||||
### Alterações na API/SDK
|
||||
|
||||
**DocumentEmbeddingsClient** retorna chunk_ids:
|
||||
```python
|
||||
return resp.chunk_ids # Changed from resp.chunks
|
||||
```
|
||||
|
||||
**Formato de dados** (DocumentEmbeddingsResponseTranslator):
|
||||
```python
|
||||
result["chunk_ids"] = obj.chunk_ids # Changed from chunks
|
||||
```
|
||||
|
||||
### Alterações na CLI
|
||||
|
||||
A ferramenta CLI exibe os chunk_ids (os chamadores podem buscar o conteúdo separadamente, se necessário).
|
||||
|
||||
## Arquivos a serem modificados
|
||||
|
||||
### Schema
|
||||
`trustgraph-base/trustgraph/schema/knowledge/embeddings.py` - ChunkEmbeddings
|
||||
`trustgraph-base/trustgraph/schema/services/query.py` - DocumentEmbeddingsResponse
|
||||
|
||||
### Mensagens/Tradutores
|
||||
`trustgraph-base/trustgraph/messaging/translators/embeddings_query.py` - DocumentEmbeddingsResponseTranslator
|
||||
|
||||
### Cliente
|
||||
`trustgraph-base/trustgraph/base/document_embeddings_client.py` - retornar chunk_ids
|
||||
|
||||
### SDK/API Python
|
||||
`trustgraph-base/trustgraph/api/flow.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/socket_client.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/async_flow.py` - se aplicável
|
||||
`trustgraph-base/trustgraph/api/bulk_client.py` - importar/exportar embeddings de documentos
|
||||
`trustgraph-base/trustgraph/api/async_bulk_client.py` - importar/exportar embeddings de documentos
|
||||
|
||||
### Serviço de Embeddings
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py` - passar chunk_id
|
||||
|
||||
### Escritores de Armazenamento
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
|
||||
### Serviços de Consulta
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/milvus/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/pinecone/service.py`
|
||||
|
||||
### Gateway
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_query.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_export.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_import.py`
|
||||
|
||||
### Document RAG
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` - adicionar cliente librarian
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` - buscar do Garage
|
||||
|
||||
### CLI
|
||||
`trustgraph-cli/trustgraph/cli/invoke_document_embeddings.py`
|
||||
`trustgraph-cli/trustgraph/cli/save_doc_embeds.py`
|
||||
`trustgraph-cli/trustgraph/cli/load_doc_embeds.py`
|
||||
|
||||
## Benefícios
|
||||
|
||||
1. Única fonte de verdade - texto do chunk apenas no Garage
|
||||
2. Redução do armazenamento do vetor
|
||||
3. Permite a rastreabilidade em tempo de consulta via chunk_id
|
||||
144
docs/tech-specs/document-embeddings-chunk-id.ru.md
Normal file
144
docs/tech-specs/document-embeddings-chunk-id.ru.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Идентификатор фрагмента встраиваний документов"
|
||||
parent: "Russian (Beta)"
|
||||
---
|
||||
|
||||
# Идентификатор фрагмента встраиваний документов
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Обзор
|
||||
|
||||
В настоящее время хранилище встраиваний документов хранит текст фрагментов непосредственно в полезной нагрузке векторного хранилища, дублируя данные, которые существуют в Garage. Данная спецификация заменяет хранение текста фрагментов ссылками на `chunk_id`.
|
||||
|
||||
## Текущее состояние
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk: bytes = b""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunks: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Структура данных для хранения векторов:
|
||||
```python
|
||||
payload={"doc": chunk} # Duplicates Garage content
|
||||
```
|
||||
|
||||
## Дизайн
|
||||
|
||||
### Изменения схемы
|
||||
|
||||
**ChunkEmbeddings** - заменить "chunk" на "chunk_id":
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk_id: str = ""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**DocumentEmbeddingsResponse** - возвращать chunk_ids вместо фрагментов:
|
||||
```python
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunk_ids: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
### Структура данных для векторного хранилища
|
||||
|
||||
Все хранилища (Qdrant, Milvus, Pinecone):
|
||||
```python
|
||||
payload={"chunk_id": chunk_id}
|
||||
```
|
||||
|
||||
### Изменения в системе извлечения информации (RAG)
|
||||
|
||||
Модуль обработки документов RAG извлекает содержимое фрагментов из системы Garage:
|
||||
|
||||
```python
|
||||
# Get chunk_ids from embeddings store
|
||||
chunk_ids = await self.rag.doc_embeddings_client.query(...)
|
||||
|
||||
# Fetch chunk content from Garage
|
||||
docs = []
|
||||
for chunk_id in chunk_ids:
|
||||
content = await self.rag.librarian_client.get_document_content(
|
||||
chunk_id, self.user
|
||||
)
|
||||
docs.append(content)
|
||||
```
|
||||
|
||||
### Изменения API/SDK
|
||||
|
||||
**DocumentEmbeddingsClient** возвращает chunk_ids:
|
||||
```python
|
||||
return resp.chunk_ids # Changed from resp.chunks
|
||||
```
|
||||
|
||||
**Формат данных** (DocumentEmbeddingsResponseTranslator):
|
||||
```python
|
||||
result["chunk_ids"] = obj.chunk_ids # Changed from chunks
|
||||
```
|
||||
|
||||
### Изменения в CLI
|
||||
|
||||
Инструмент CLI отображает идентификаторы фрагментов (пользователи могут извлекать контент отдельно, если это необходимо).
|
||||
|
||||
## Файлы для изменения
|
||||
|
||||
### Схема
|
||||
`trustgraph-base/trustgraph/schema/knowledge/embeddings.py` - ChunkEmbeddings
|
||||
`trustgraph-base/trustgraph/schema/services/query.py` - DocumentEmbeddingsResponse
|
||||
|
||||
### Сообщения/Переводчики
|
||||
`trustgraph-base/trustgraph/messaging/translators/embeddings_query.py` - DocumentEmbeddingsResponseTranslator
|
||||
|
||||
### Клиент
|
||||
`trustgraph-base/trustgraph/base/document_embeddings_client.py` - возвращать идентификаторы фрагментов
|
||||
|
||||
### Python SDK/API
|
||||
`trustgraph-base/trustgraph/api/flow.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/socket_client.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/async_flow.py` - если применимо
|
||||
`trustgraph-base/trustgraph/api/bulk_client.py` - импорт/экспорт векторных представлений документов
|
||||
`trustgraph-base/trustgraph/api/async_bulk_client.py` - импорт/экспорт векторных представлений документов
|
||||
|
||||
### Сервис векторных представлений
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py` - передавать идентификатор фрагмента
|
||||
|
||||
### Модули записи в хранилище
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
|
||||
### Сервисы запросов
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/milvus/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/pinecone/service.py`
|
||||
|
||||
### Шлюз
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_query.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_export.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_import.py`
|
||||
|
||||
### Document RAG
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` - добавить клиент librarian
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` - извлекать из Garage
|
||||
|
||||
### CLI
|
||||
`trustgraph-cli/trustgraph/cli/invoke_document_embeddings.py`
|
||||
`trustgraph-cli/trustgraph/cli/save_doc_embeds.py`
|
||||
`trustgraph-cli/trustgraph/cli/load_doc_embeds.py`
|
||||
|
||||
## Преимущества
|
||||
|
||||
1. Единый источник истины - текст фрагментов только в Garage
|
||||
2. Уменьшение объема хранимых векторных представлений
|
||||
3. Обеспечивает отслеживание происхождения данных в момент запроса с помощью идентификатора фрагмента.
|
||||
144
docs/tech-specs/document-embeddings-chunk-id.sw.md
Normal file
144
docs/tech-specs/document-embeddings-chunk-id.sw.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Kitambulisho cha Sehemu ya Matini (Document Embeddings Chunk ID)"
|
||||
parent: "Swahili (Beta)"
|
||||
---
|
||||
|
||||
# Kitambulisho cha Sehemu ya Matini (Document Embeddings Chunk ID)
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Muhtasari
|
||||
|
||||
Hifadhi ya matini ya maandishi kwa sasa huhifadhi matini ya sehemu moja kwa moja katika sehemu ya data ya hifadhi ya vector, na hivyo kurudia data ambayo ipo katika Garage. Hati hii inabadilisha uhifadhi wa matini ya sehemu kwa kutumia marejeleo ya `chunk_id`.
|
||||
|
||||
## Hali ya Sasa
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk: bytes = b""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunks: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Hifadhi ya data ya aina ya vector:
|
||||
```python
|
||||
payload={"doc": chunk} # Duplicates Garage content
|
||||
```
|
||||
|
||||
## Ubunifu
|
||||
|
||||
### Mabadiliko ya Mpango
|
||||
|
||||
**ChunkEmbeddings** - badilisha "chunk" na "chunk_id":
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk_id: str = ""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**Jibu la DocumentEmbeddingsResponse** - irudishe `chunk_ids` badala ya `chunks`:
|
||||
```python
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunk_ids: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
### Mfumo wa Hifadhi ya Vektor
|
||||
|
||||
Maduka yote (Qdrant, Milvus, Pinecone):
|
||||
```python
|
||||
payload={"chunk_id": chunk_id}
|
||||
```
|
||||
|
||||
### Mabadiliko ya Mchakato wa RAG wa Hati
|
||||
|
||||
Mchakato wa RAG wa hati hupata maudhui ya sehemu kutoka kwa Garage:
|
||||
|
||||
```python
|
||||
# Get chunk_ids from embeddings store
|
||||
chunk_ids = await self.rag.doc_embeddings_client.query(...)
|
||||
|
||||
# Fetch chunk content from Garage
|
||||
docs = []
|
||||
for chunk_id in chunk_ids:
|
||||
content = await self.rag.librarian_client.get_document_content(
|
||||
chunk_id, self.user
|
||||
)
|
||||
docs.append(content)
|
||||
```
|
||||
|
||||
### Mabadiliko ya API/SDK
|
||||
|
||||
**DocumentEmbeddingsClient** hurudia chunk_ids:
|
||||
```python
|
||||
return resp.chunk_ids # Changed from resp.chunks
|
||||
```
|
||||
|
||||
**Muundo wa data** (Mfasiri wa Majibu ya Matangazo ya Hati):
|
||||
```python
|
||||
result["chunk_ids"] = obj.chunk_ids # Changed from chunks
|
||||
```
|
||||
|
||||
### Mabadiliko ya CLI
|
||||
|
||||
Zana ya CLI inaonyesha kitambulisho cha vipande (watumiaji wanaweza kupata maudhui kando ikiwa ni lazima).
|
||||
|
||||
## Faili Zinazohitajika Kubadilishwa
|
||||
|
||||
### Mpango (Schema)
|
||||
`trustgraph-base/trustgraph/schema/knowledge/embeddings.py` - ChunkEmbeddings
|
||||
`trustgraph-base/trustgraph/schema/services/query.py` - DocumentEmbeddingsResponse
|
||||
|
||||
### Ujumbe/Watafsiri
|
||||
`trustgraph-base/trustgraph/messaging/translators/embeddings_query.py` - DocumentEmbeddingsResponseTranslator
|
||||
|
||||
### Mteja (Client)
|
||||
`trustgraph-base/trustgraph/base/document_embeddings_client.py` - rudisha kitambulisho cha vipande
|
||||
|
||||
### SDK/API ya Python
|
||||
`trustgraph-base/trustgraph/api/flow.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/socket_client.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/async_flow.py` - ikiwa inafaa
|
||||
`trustgraph-base/trustgraph/api/bulk_client.py` - uagizaji/uangamizi wa vipande vya maandishi
|
||||
`trustgraph-base/trustgraph/api/async_bulk_client.py` - uagizaji/uangamizi wa vipande vya maandishi
|
||||
|
||||
### Huduma ya Vipande vya Maandishi (Embeddings Service)
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py` - pitisha kitambulisho cha kipande
|
||||
|
||||
### Waandishi wa Uhifadhi (Storage Writers)
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
|
||||
### Huduma za Utafutaji (Query Services)
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/milvus/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/pinecone/service.py`
|
||||
|
||||
### Lango (Gateway)
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_query.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_export.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_import.py`
|
||||
|
||||
### Utafutaji wa Hati (Document RAG)
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` - ongeza mteja wa "librarian"
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` - pata kutoka "Garage"
|
||||
|
||||
### CLI
|
||||
`trustgraph-cli/trustgraph/cli/invoke_document_embeddings.py`
|
||||
`trustgraph-cli/trustgraph/cli/save_doc_embeds.py`
|
||||
`trustgraph-cli/trustgraph/cli/load_doc_embeds.py`
|
||||
|
||||
## Faida
|
||||
|
||||
1. Chanzo kimoja cha ukweli - maandishi ya vipande tu katika "Garage"
|
||||
2. Kupunguzwa kwa uhifadhi wa hifadhi ya vector
|
||||
3. Inawezesha uhakikisho wa muda wa utafutaji kupitia kitambulisho cha kipande.
|
||||
144
docs/tech-specs/document-embeddings-chunk-id.tr.md
Normal file
144
docs/tech-specs/document-embeddings-chunk-id.tr.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Belge Gömme Parçası Kimliği"
|
||||
parent: "Turkish (Beta)"
|
||||
---
|
||||
|
||||
# Belge Gömme Parçası Kimliği
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Genel Bakış
|
||||
|
||||
Belge gömme depolaması şu anda parça metnini doğrudan vektör deposu yüküne kaydederek, Garage'da bulunan verilerin çoğaltılmasına neden oluyor. Bu özellik, parça metni depolamasını `chunk_id` referanslarıyla değiştirmektedir.
|
||||
|
||||
## Mevcut Durum
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk: bytes = b""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunks: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Vektör depolama yükü:
|
||||
```python
|
||||
payload={"doc": chunk} # Duplicates Garage content
|
||||
```
|
||||
|
||||
## Tasarım
|
||||
|
||||
### Şema Değişiklikleri
|
||||
|
||||
**ChunkEmbeddings** - chunk'ı chunk_id ile değiştirin:
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk_id: str = ""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**DocumentEmbeddingsResponse** - parçalar yerine chunk_id'leri döndür:
|
||||
```python
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunk_ids: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
### Vektör Depolama Veri Yapısı
|
||||
|
||||
Tüm depolar (Qdrant, Milvus, Pinecone):
|
||||
```python
|
||||
payload={"chunk_id": chunk_id}
|
||||
```
|
||||
|
||||
### Belge RAG Değişiklikleri
|
||||
|
||||
Belge RAG işlemcisi, parça içeriğini Garage'dan alır:
|
||||
|
||||
```python
|
||||
# Get chunk_ids from embeddings store
|
||||
chunk_ids = await self.rag.doc_embeddings_client.query(...)
|
||||
|
||||
# Fetch chunk content from Garage
|
||||
docs = []
|
||||
for chunk_id in chunk_ids:
|
||||
content = await self.rag.librarian_client.get_document_content(
|
||||
chunk_id, self.user
|
||||
)
|
||||
docs.append(content)
|
||||
```
|
||||
|
||||
### API/SDK Değişiklikleri
|
||||
|
||||
**DocumentEmbeddingsClient**, `chunk_ids` değerini döndürür:
|
||||
```python
|
||||
return resp.chunk_ids # Changed from resp.chunks
|
||||
```
|
||||
|
||||
**Kablolu format** (DocumentEmbeddingsResponseTranslator):
|
||||
```python
|
||||
result["chunk_ids"] = obj.chunk_ids # Changed from chunks
|
||||
```
|
||||
|
||||
### CLI Değişiklikleri
|
||||
|
||||
CLI aracı, chunk_id'leri gösterir (çağrıcılar, gerekirse içeriği ayrı olarak alabilir).
|
||||
|
||||
## Değiştirilecek Dosyalar
|
||||
|
||||
### Şema
|
||||
`trustgraph-base/trustgraph/schema/knowledge/embeddings.py` - ChunkEmbeddings
|
||||
`trustgraph-base/trustgraph/schema/services/query.py` - DocumentEmbeddingsResponse
|
||||
|
||||
### Mesajlaşma/Çeviriciler
|
||||
`trustgraph-base/trustgraph/messaging/translators/embeddings_query.py` - DocumentEmbeddingsResponseTranslator
|
||||
|
||||
### İstemci
|
||||
`trustgraph-base/trustgraph/base/document_embeddings_client.py` - chunk_id'leri döndür
|
||||
|
||||
### Python SDK/API
|
||||
`trustgraph-base/trustgraph/api/flow.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/socket_client.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/async_flow.py` - eğer uygunsa
|
||||
`trustgraph-base/trustgraph/api/bulk_client.py` - belge gömülerinin içe/dışa aktarımı
|
||||
`trustgraph-base/trustgraph/api/async_bulk_client.py` - belge gömülerinin içe/dışa aktarımı
|
||||
|
||||
### Gömme Hizmeti
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py` - chunk_id'yi ilet
|
||||
|
||||
### Depolama Yazıcıları
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
|
||||
### Sorgu Hizmetleri
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/milvus/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/pinecone/service.py`
|
||||
|
||||
### Ağ Geçidi
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_query.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_export.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_import.py`
|
||||
|
||||
### Belge RAG
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` - librarian istemcisini ekle
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` - Garage'dan al
|
||||
|
||||
### CLI
|
||||
`trustgraph-cli/trustgraph/cli/invoke_document_embeddings.py`
|
||||
`trustgraph-cli/trustgraph/cli/save_doc_embeds.py`
|
||||
`trustgraph-cli/trustgraph/cli/load_doc_embeds.py`
|
||||
|
||||
## Faydalar
|
||||
|
||||
1. Tek kaynaklı doğruluk - chunk metni yalnızca Garage'da bulunur.
|
||||
2. Vektör depolama alanında azalma.
|
||||
3. chunk_id aracılığıyla sorgu zamanı köken bilgisini sağlar.
|
||||
144
docs/tech-specs/document-embeddings-chunk-id.zh-cn.md
Normal file
144
docs/tech-specs/document-embeddings-chunk-id.zh-cn.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
layout: default
|
||||
title: "文档嵌入块 ID"
|
||||
parent: "Chinese (Beta)"
|
||||
---
|
||||
|
||||
# 文档嵌入块 ID
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## 概述
|
||||
|
||||
目前,文档嵌入存储将块文本直接存储在向量存储的负载中,这会重复 Garage 中已存在的数据。此规范将块文本存储替换为对 `chunk_id` 的引用。
|
||||
|
||||
## 当前状态
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk: bytes = b""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunks: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
向量存储负载:
|
||||
```python
|
||||
payload={"doc": chunk} # Duplicates Garage content
|
||||
```
|
||||
|
||||
## 设计
|
||||
|
||||
### 模式变更
|
||||
|
||||
**ChunkEmbeddings** - 将 chunk 替换为 chunk_id:
|
||||
```python
|
||||
@dataclass
|
||||
class ChunkEmbeddings:
|
||||
chunk_id: str = ""
|
||||
vectors: list[list[float]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**DocumentEmbeddingsResponse** - 返回 chunk_ids 而不是 chunks:
|
||||
```python
|
||||
@dataclass
|
||||
class DocumentEmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
chunk_ids: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
### 向量存储负载
|
||||
|
||||
所有存储(Qdrant、Milvus、Pinecone):
|
||||
```python
|
||||
payload={"chunk_id": chunk_id}
|
||||
```
|
||||
|
||||
### 文档 RAG 变更
|
||||
|
||||
文档 RAG 处理器从 Garage 中获取块内容:
|
||||
|
||||
```python
|
||||
# Get chunk_ids from embeddings store
|
||||
chunk_ids = await self.rag.doc_embeddings_client.query(...)
|
||||
|
||||
# Fetch chunk content from Garage
|
||||
docs = []
|
||||
for chunk_id in chunk_ids:
|
||||
content = await self.rag.librarian_client.get_document_content(
|
||||
chunk_id, self.user
|
||||
)
|
||||
docs.append(content)
|
||||
```
|
||||
|
||||
### API/SDK 变更
|
||||
|
||||
**DocumentEmbeddingsClient** 返回 chunk_ids:
|
||||
```python
|
||||
return resp.chunk_ids # Changed from resp.chunks
|
||||
```
|
||||
|
||||
**数据格式** (DocumentEmbeddingsResponseTranslator):
|
||||
```python
|
||||
result["chunk_ids"] = obj.chunk_ids # Changed from chunks
|
||||
```
|
||||
|
||||
### CLI 变更
|
||||
|
||||
CLI 工具显示 chunk_ids(如果需要,调用者可以单独获取内容)。
|
||||
|
||||
## 需要修改的文件
|
||||
|
||||
### Schema
|
||||
`trustgraph-base/trustgraph/schema/knowledge/embeddings.py` - ChunkEmbeddings
|
||||
`trustgraph-base/trustgraph/schema/services/query.py` - DocumentEmbeddingsResponse
|
||||
|
||||
### 消息/翻译器
|
||||
`trustgraph-base/trustgraph/messaging/translators/embeddings_query.py` - DocumentEmbeddingsResponseTranslator
|
||||
|
||||
### 客户端
|
||||
`trustgraph-base/trustgraph/base/document_embeddings_client.py` - 返回 chunk_ids
|
||||
|
||||
### Python SDK/API
|
||||
`trustgraph-base/trustgraph/api/flow.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/socket_client.py` - document_embeddings_query
|
||||
`trustgraph-base/trustgraph/api/async_flow.py` - 如果适用
|
||||
`trustgraph-base/trustgraph/api/bulk_client.py` - 导入/导出文档嵌入
|
||||
`trustgraph-base/trustgraph/api/async_bulk_client.py` - 导入/导出文档嵌入
|
||||
|
||||
### 嵌入服务
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py` - 传递 chunk_id
|
||||
|
||||
### 存储写入器
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
|
||||
### 查询服务
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/qdrant/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/milvus/service.py`
|
||||
`trustgraph-flow/trustgraph/query/doc_embeddings/pinecone/service.py`
|
||||
|
||||
### 网关
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_query.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_export.py`
|
||||
`trustgraph-flow/trustgraph/gateway/dispatch/document_embeddings_import.py`
|
||||
|
||||
### 文档 RAG
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/rag.py` - 添加 librarian 客户端
|
||||
`trustgraph-flow/trustgraph/retrieval/document_rag/document_rag.py` - 从 Garage 获取
|
||||
|
||||
### CLI
|
||||
`trustgraph-cli/trustgraph/cli/invoke_document_embeddings.py`
|
||||
`trustgraph-cli/trustgraph/cli/save_doc_embeds.py`
|
||||
`trustgraph-cli/trustgraph/cli/load_doc_embeds.py`
|
||||
|
||||
## 优点
|
||||
|
||||
1. 单一数据源 - 仅在 Garage 中存储文本块
|
||||
2. 减少向量存储空间
|
||||
3. 通过 chunk_id 实现查询时的数据溯源
|
||||
675
docs/tech-specs/embeddings-batch-processing.ar.md
Normal file
675
docs/tech-specs/embeddings-batch-processing.ar.md
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
---
|
||||
layout: default
|
||||
title: "المواصفات الفنية لمعالجة الدفعات لخدمة التضمينات (Embeddings)"
|
||||
parent: "Arabic (Beta)"
|
||||
---
|
||||
|
||||
# المواصفات الفنية لمعالجة الدفعات لخدمة التضمينات (Embeddings)
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
تصف هذه المواصفات التحسينات التي ستُجرى على خدمة التضمينات لدعم معالجة الدفعات لعدد كبير من النصوص في طلب واحد. تعالج التنفيذ الحالي النص الواحد في كل مرة، مما يفوّت المزايا الكبيرة في الأداء التي توفرها نماذج التضمين عند معالجة الدفعات.
|
||||
|
||||
1. **عدم كفاءة معالجة النصوص الفردية**: يغلف التنفيذ الحالي النصوص الفردية في قائمة، مما يؤدي إلى عدم الاستفادة الكاملة من قدرات الدفعات في FastEmbed.
|
||||
2. **العبء الزائد لكل طلب نص**: يتطلب كل نص رسالة Pulsar منفصلة، مما يتطلب جولة ذهاب وإياب.
|
||||
3. **عدم كفاءة استنتاج النموذج**: نماذج التضمين لها عبء ثابت لكل دفعة؛ فإن الدفعات الصغيرة تهدر موارد وحدة معالجة الرسومات (GPU) ووحدة المعالجة المركزية (CPU).
|
||||
4. **المعالجة التسلسلية في التطبيقات**: تقوم الخدمات الرئيسية بالتكرار على العناصر واستدعاء التضمينات واحدًا تلو الآخر.
|
||||
|
||||
## الأهداف
|
||||
|
||||
**دعم واجهة برمجة تطبيقات (API) للدفعات**: تمكين معالجة نصوص متعددة في طلب واحد.
|
||||
**التوافق مع الإصدارات السابقة**: الحفاظ على دعم الطلبات التي تتضمن نصًا واحدًا فقط.
|
||||
**تحسين كبير في الإنتاجية**: استهداف تحسين في الإنتاجية يتراوح بين 5 إلى 10 مرات للعمليات الجماعية.
|
||||
**تقليل زمن الوصول لكل نص**: تقليل زمن الوصول المتوسط عند تضمين نصوص متعددة.
|
||||
**كفاءة الذاكرة**: معالجة الدفعات دون استهلاك مفرط للذاكرة.
|
||||
**الاستقلالية عن المزود**: دعم التجميع عبر FastEmbed و Ollama ومزودين آخرين.
|
||||
**تحديث التطبيقات**: تحديث جميع تطبيقات التضمين لاستخدام واجهة برمجة تطبيقات الدفعات عند الإمكان.
|
||||
|
||||
## الخلفية
|
||||
|
||||
### التنفيذ الحالي - خدمة التضمينات
|
||||
|
||||
يُظهر تطبيق التضمينات في `trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` عدم كفاءة كبيرة في الأداء:
|
||||
|
||||
```python
|
||||
# fastembed/processor.py line 56
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
vecs = self.embeddings.embed([text]) # Single text wrapped in list
|
||||
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**المشاكل:**
|
||||
|
||||
1. **حجم الدفعة 1**: طريقة `embed()` في FastEmbed مُحسّنة للمعالجة الدفعية، ولكننا نستدعيها دائمًا مع `[text]` - دفعة بحجم 1.
|
||||
|
||||
2. **التكلفة لكل طلب**: كل طلب تضمين يتضمن:
|
||||
تسلسل/إلغاء تسلسل رسالة Pulsar.
|
||||
زمن انتقال الشبكة.
|
||||
تكلفة بدء تشغيل الاستدلال للنموذج.
|
||||
تكلفة جدولة المهام غير المتزامنة في Python.
|
||||
|
||||
3. **قيود المخطط**: مخطط `EmbeddingsRequest` يدعم نصًا واحدًا فقط:
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
text: str = "" # Single text only
|
||||
```
|
||||
|
||||
### المستخدمون الحاليون - المعالجة التسلسلية
|
||||
|
||||
#### 1. بوابة واجهة برمجة التطبيقات (API Gateway)
|
||||
|
||||
**الملف:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
تقبل البوابة طلبات تضمين النصوص الفردية عبر HTTP/WebSocket وتوجهها إلى خدمة التضمين. حاليًا، لا يوجد نقطة نهاية للدفعات.
|
||||
|
||||
```python
|
||||
class EmbeddingsRequestor(ServiceRequestor):
|
||||
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
||||
request_schema=EmbeddingsRequest, # Single text only
|
||||
response_schema=EmbeddingsResponse,
|
||||
```
|
||||
|
||||
**التأثير:** يجب على العملاء الخارجيين (تطبيقات الويب، النصوص البرمجية) إجراء N طلب HTTP لتضمين N نص.
|
||||
|
||||
#### 2. خدمة تضمين المستندات
|
||||
|
||||
**الملف:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
يعالج أجزاء المستندات واحدة تلو الأخرى:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
v = msg.value()
|
||||
|
||||
# Single chunk per request
|
||||
resp = await flow("embeddings-request").request(
|
||||
EmbeddingsRequest(text=v.chunk)
|
||||
)
|
||||
vectors = resp.vectors
|
||||
```
|
||||
|
||||
**التأثير:** تتطلب كل جزء من المستند استدعاءً منفصلاً لعملية التضمين. المستند الذي يتكون من 100 جزء = 100 طلب تضمين.
|
||||
|
||||
#### 3. خدمة تضمين الرسوم البيانية
|
||||
|
||||
**الملف:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
|
||||
يتكرر على الكيانات ويقوم بتضمين كل منها بالتسلسل:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for entity in v.entities:
|
||||
# Serial embedding - one entity at a time
|
||||
vectors = await flow("embeddings-request").embed(
|
||||
text=entity.context
|
||||
)
|
||||
entities.append(EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors,
|
||||
chunk_id=entity.chunk_id,
|
||||
))
|
||||
```
|
||||
|
||||
**التأثير:** رسالة تحتوي على 50 كيانًا = 50 طلب تضمين تسلسلي. هذا يمثل عنق زجاجة رئيسي أثناء بناء الرسم البياني المعرفي.
|
||||
|
||||
#### 4. خدمة تضمين الصفوف
|
||||
|
||||
**الملف:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
|
||||
يتكرر على النصوص الفريدة ويضمّن كل منها بشكل تسلسلي:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
# Serial embedding - one text at a time
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
|
||||
embeddings_list.append(RowIndexEmbedding(
|
||||
index_name=index_name,
|
||||
index_value=index_value,
|
||||
text=text,
|
||||
vectors=vectors
|
||||
))
|
||||
```
|
||||
|
||||
**التأثير:** معالجة جدول يحتوي على 100 قيمة فريدة مفهرسة = 100 طلب تضمين متسلسل.
|
||||
|
||||
#### 5. EmbeddingsClient (العميل الأساسي)
|
||||
|
||||
**الملف:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
العميل المستخدم من قبل جميع معالجات التدفق يدعم فقط تضمين النصوص الفردية:
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(self, text, timeout=30):
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(text=text), # Single text
|
||||
timeout=timeout
|
||||
)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
**التأثير:** جميع المستخدمين الذين يعتمدون على هذا البرنامج يقتصرون على العمليات النصية البسيطة.
|
||||
|
||||
#### 6. أدوات سطر الأوامر
|
||||
|
||||
**الملف:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
أداة سطر الأوامر تقبل وسيط نصي واحد:
|
||||
|
||||
```python
|
||||
def query(url, flow_id, text, token=None):
|
||||
result = flow.embeddings(text=text) # Single text
|
||||
vectors = result.get("vectors", [])
|
||||
```
|
||||
|
||||
**التأثير:** لا يمكن للمستخدمين إجراء تضمين مجمّع من سطر الأوامر. يتطلب معالجة ملف من النصوص عدد N من الاستدعاءات.
|
||||
|
||||
#### 7. حزمة تطوير البرمجيات (SDK) الخاصة بـ Python
|
||||
|
||||
توفر حزمة تطوير البرمجيات الخاصة بـ Python فئتين من العملاء للتفاعل مع خدمات TrustGraph. تدعم كلتاهما فقط التضمين لنص واحد.
|
||||
|
||||
**الملف:** `trustgraph-base/trustgraph/api/flow.py`
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, text):
|
||||
"""Get embeddings for a single text"""
|
||||
input = {"text": text}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**الملف:** `trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, text: str, **kwargs: Any) -> Dict[str, Any]:
|
||||
"""Get embeddings for a single text via WebSocket"""
|
||||
request = {"text": text}
|
||||
return self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
```
|
||||
|
||||
**التأثير:** يجب على مطوري بايثون الذين يستخدمون مجموعة تطوير البرامج (SDK) المرور على النصوص وإجراء مكالمات واجهة برمجة التطبيقات (API) منفصلة. لا يوجد دعم لعمليات الدمج المجمعة لمستخدمي مجموعة تطوير البرامج.
|
||||
|
||||
### تأثير الأداء
|
||||
|
||||
بالنسبة لاستيعاب المستندات النموذجي (1000 جزء نصي):
|
||||
**الحالي:** 1000 طلب منفصل، و1000 استدعاء لنموذج الاستدلال.
|
||||
**مجمعة (batch_size=32):** 32 طلبًا، و32 استدعاء لنموذج الاستدلال (انخفاض بنسبة 96.8٪).
|
||||
|
||||
بالنسبة لدمج الرسم البياني (رسالة تحتوي على 50 كيانًا):
|
||||
**الحالي:** 50 استدعاء انتظار متسلسل، من 5 إلى 10 ثوانٍ تقريبًا.
|
||||
**مجمعة:** 1-2 استدعاء مجمع، من 0.5 إلى 1 ثانية تقريبًا (تحسين بمقدار 5-10 مرات).
|
||||
|
||||
تحقق مكتبات FastEmbed والمكتبات المماثلة تقريبًا من قابلية التوسع الخطية في الإنتاجية مع حجم الدفعة حتى حدود الأجهزة (عادةً ما تكون 32-128 نصًا لكل دفعة).
|
||||
|
||||
## التصميم الفني
|
||||
|
||||
### البنية
|
||||
|
||||
يتطلب تحسين معالجة الدفعات لإنشاء تضمينات تغييرات في المكونات التالية:
|
||||
|
||||
#### 1. **تحسين المخطط**
|
||||
قم بتوسيع `EmbeddingsRequest` لدعم نصوص متعددة.
|
||||
قم بتوسيع `EmbeddingsResponse` لإرجاع مجموعات متجهات متعددة.
|
||||
حافظ على التوافق مع الإصدارات السابقة مع طلبات النص الواحد.
|
||||
|
||||
الوحدة: `trustgraph-base/trustgraph/schema/services/llm.py`
|
||||
|
||||
#### 2. **تحسين الخدمة الأساسية**
|
||||
قم بتحديث `EmbeddingsService` للتعامل مع الطلبات المجمعة.
|
||||
أضف تكوين حجم الدفعة.
|
||||
قم بتنفيذ معالجة الطلبات الواعية بالدفعة.
|
||||
|
||||
الوحدة: `trustgraph-base/trustgraph/base/embeddings_service.py`
|
||||
|
||||
#### 3. **تحديثات معالج المزود**
|
||||
قم بتحديث معالج FastEmbed لتمرير الدفعة الكاملة إلى `embed()`.
|
||||
قم بتحديث معالج Ollama للتعامل مع الدفعات (إذا تم الدعم).
|
||||
أضف معالجة تسلسلية احتياطية للمزودين الذين لا يدعمون الدفعات.
|
||||
|
||||
الوحدات:
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
||||
|
||||
#### 4. **تحسين العميل**
|
||||
أضف طريقة إنشاء تضمينات مجمعة إلى `EmbeddingsClient`.
|
||||
دعم كل من واجهات برمجة التطبيقات الفردية والمجمعة.
|
||||
أضف تجميعًا تلقائيًا للمدخلات الكبيرة.
|
||||
|
||||
الوحدة: `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
#### 5. **تحديثات المتصل - معالجات التدفق**
|
||||
قم بتحديث `graph_embeddings` لتجميع سياقات الكيانات.
|
||||
قم بتحديث `row_embeddings` لتجميع نصوص الفهرس.
|
||||
قم بتحديث `document_embeddings` إذا كان تجميع الرسائل ممكنًا.
|
||||
|
||||
الوحدات:
|
||||
`trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
#### 6. **تحسين بوابة واجهة برمجة التطبيقات**
|
||||
أضف نقطة نهاية لإنشاء تضمينات مجمعة.
|
||||
دعم مصفوفة من النصوص في نص الطلب.
|
||||
|
||||
الوحدة: `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
#### 7. **تحسين أداة سطر الأوامر**
|
||||
أضف دعمًا للنصوص المتعددة أو إدخال الملف.
|
||||
أضف معلمة حجم الدفعة.
|
||||
|
||||
الوحدة: `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
#### 8. **تحسين مجموعة تطوير البرامج (SDK) الخاصة بـ Python**
|
||||
أضف طريقة `embeddings_batch()` إلى `FlowInstance`.
|
||||
أضف طريقة `embeddings_batch()` إلى `SocketFlowInstance`.
|
||||
دعم كل من واجهات برمجة التطبيقات الفردية والمجمعة لمستخدمي مجموعة تطوير البرامج.
|
||||
|
||||
الوحدات:
|
||||
`trustgraph-base/trustgraph/api/flow.py`
|
||||
`trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
### نماذج البيانات
|
||||
|
||||
#### EmbeddingsRequest
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
الاستخدام:
|
||||
نص مفرد: `EmbeddingsRequest(texts=["hello world"])`
|
||||
دفعة: `EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
||||
|
||||
#### EmbeddingsResponse
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
هيكل الاستجابة:
|
||||
`vectors[i]` يحتوي على مجموعة المتجهات لـ `texts[i]`
|
||||
كل مجموعة متجهات هي `list[list[float]]` (قد تُرجع النماذج عدة متجهات لكل نص)
|
||||
مثال: 3 نصوص → `vectors` يحتوي على 3 إدخالات، كل منها يحتوي على تضمينات هذا النص
|
||||
|
||||
### واجهات برمجة التطبيقات (APIs)
|
||||
|
||||
#### EmbeddingsClient
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(
|
||||
self,
|
||||
texts: list[str],
|
||||
timeout: float = 300,
|
||||
) -> list[list[list[float]]]:
|
||||
"""
|
||||
Embed one or more texts in a single request.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
timeout: Timeout for the operation
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(texts=texts),
|
||||
timeout=timeout
|
||||
)
|
||||
if resp.error:
|
||||
raise RuntimeError(resp.error.message)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
#### نقطة نهاية تضمين بوابة واجهة برمجة التطبيقات (API Gateway).
|
||||
|
||||
تم تحديث نقطة النهاية لدعم التضمين الفردي أو الدفعي:
|
||||
|
||||
```
|
||||
POST /api/v1/embeddings
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"texts": ["text1", "text2", "text3"],
|
||||
"flow_id": "default"
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"vectors": [
|
||||
[[0.1, 0.2, ...]],
|
||||
[[0.3, 0.4, ...]],
|
||||
[[0.5, 0.6, ...]]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### تفاصيل التنفيذ
|
||||
|
||||
#### المرحلة الأولى: تغييرات المخطط
|
||||
|
||||
**EmbeddingsRequest:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**الاستجابة المضمنة:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**تم تحديث `EmbeddingsService.on_request`:**
|
||||
```python
|
||||
async def on_request(self, msg, consumer, flow):
|
||||
request = msg.value()
|
||||
id = msg.properties()["id"]
|
||||
model = flow("model")
|
||||
|
||||
vectors = await self.on_embeddings(request.texts, model=model)
|
||||
response = EmbeddingsResponse(error=None, vectors=vectors)
|
||||
|
||||
await flow("response").send(response, properties={"id": id})
|
||||
```
|
||||
|
||||
#### المرحلة الثانية: تحديث معالج FastEmbed
|
||||
|
||||
**الحالي (غير فعال):**
|
||||
```python
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
vecs = self.embeddings.embed([text]) # Batch of 1
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**تحديث:**
|
||||
```python
|
||||
async def on_embeddings(self, texts: list[str], model=None):
|
||||
"""Embed texts - processes all texts in single model call"""
|
||||
if not texts:
|
||||
return []
|
||||
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
# FastEmbed handles the full batch efficiently
|
||||
all_vecs = list(self.embeddings.embed(texts))
|
||||
|
||||
# Return list of vector sets, one per input text
|
||||
return [[v.tolist()] for v in all_vecs]
|
||||
```
|
||||
|
||||
#### المرحلة الثالثة: تحديث خدمة تضمين الرسوم البيانية
|
||||
|
||||
**الحالي (التسلسلي):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
entities = []
|
||||
for entity in v.entities:
|
||||
vectors = await flow("embeddings-request").embed(text=entity.context)
|
||||
entities.append(EntityEmbeddings(...))
|
||||
```
|
||||
|
||||
**تحديث (مجموعة):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
# Collect all contexts
|
||||
contexts = [entity.context for entity in v.entities]
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=contexts)
|
||||
|
||||
# Pair results with entities
|
||||
entities = [
|
||||
EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors[0], # First vector from the set
|
||||
chunk_id=entity.chunk_id,
|
||||
)
|
||||
for entity, vectors in zip(v.entities, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### المرحلة الرابعة: تحديث خدمة تضمين الصفوف
|
||||
|
||||
**الحالي (تسلسلي):**
|
||||
```python
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
embeddings_list.append(RowIndexEmbedding(...))
|
||||
```
|
||||
|
||||
**تحديث (مجموعة):**
|
||||
```python
|
||||
# Collect texts and metadata
|
||||
texts = list(texts_to_embed.keys())
|
||||
metadata = list(texts_to_embed.values())
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=texts)
|
||||
|
||||
# Pair results
|
||||
embeddings_list = [
|
||||
RowIndexEmbedding(
|
||||
index_name=meta[0],
|
||||
index_value=meta[1],
|
||||
text=text,
|
||||
vectors=vectors[0] # First vector from the set
|
||||
)
|
||||
for text, meta, vectors in zip(texts, metadata, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### المرحلة الخامسة: تحسين أداة سطر الأوامر.
|
||||
|
||||
**سطر الأوامر المحدث:**
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(...)
|
||||
|
||||
parser.add_argument(
|
||||
'text',
|
||||
nargs='*', # Zero or more texts
|
||||
help='Text(s) to convert to embedding vectors',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--file',
|
||||
help='File containing texts (one per line)',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--batch-size',
|
||||
type=int,
|
||||
default=32,
|
||||
help='Batch size for processing (default: 32)',
|
||||
)
|
||||
```
|
||||
|
||||
الاستخدام:
|
||||
```bash
|
||||
# Single text (existing)
|
||||
tg-invoke-embeddings "hello world"
|
||||
|
||||
# Multiple texts
|
||||
tg-invoke-embeddings "text one" "text two" "text three"
|
||||
|
||||
# From file
|
||||
tg-invoke-embeddings -f texts.txt --batch-size 64
|
||||
```
|
||||
|
||||
#### المرحلة السادسة: تحسين حزمة تطوير البرمجيات (SDK) الخاصة بـ Python
|
||||
|
||||
**FlowInstance (عميل HTTP):**
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, texts: list[str]) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
input = {"texts": texts}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**مثيل SocketFlow (عميل WebSocket):**
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts via WebSocket.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
request = {"texts": texts}
|
||||
response = self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
return response["vectors"]
|
||||
```
|
||||
|
||||
**أمثلة على استخدام الـ SDK:**
|
||||
|
||||
```python
|
||||
# Single text
|
||||
vectors = flow.embeddings(["hello world"])
|
||||
print(f"Dimensions: {len(vectors[0][0])}")
|
||||
|
||||
# Batch embedding
|
||||
texts = ["text one", "text two", "text three"]
|
||||
all_vectors = flow.embeddings(texts)
|
||||
|
||||
# Process results
|
||||
for text, vecs in zip(texts, all_vectors):
|
||||
print(f"{text}: {len(vecs[0])} dimensions")
|
||||
```
|
||||
|
||||
## اعتبارات الأمان
|
||||
|
||||
**حدود حجم الطلب**: فرض الحد الأقصى لحجم الدفعة لمنع استنزاف الموارد.
|
||||
**معالجة انتهاء المهلة**: قم بتعيين قيم انتهاء المهلة بشكل مناسب لحجم الدفعة.
|
||||
**حدود الذاكرة**: راقب استخدام الذاكرة للدفعات الكبيرة.
|
||||
**التحقق من صحة الإدخال**: تحقق من صحة جميع النصوص في الدفعة قبل المعالجة.
|
||||
|
||||
## اعتبارات الأداء
|
||||
|
||||
### التحسينات المتوقعة
|
||||
|
||||
**معدل الإنتاجية:**
|
||||
نص واحد: ~10-50 نصًا/ثانية (حسب النموذج)
|
||||
دفعة (حجم 32): ~200-500 نص/ثانية (تحسين بمقدار 5-10 مرات)
|
||||
|
||||
**زمن الوصول لكل نص:**
|
||||
نص واحد: 50-200 مللي ثانية لكل نص
|
||||
دفعة (حجم 32): 5-20 مللي ثانية لكل نص (متوسط)
|
||||
|
||||
**التحسينات الخاصة بالخدمة:**
|
||||
|
||||
| الخدمة | الحالي | الدفعات | التحسين |
|
||||
|---------|---------|---------|-------------|
|
||||
| تضمينات الرسم البياني (50 كيانًا) | 5-10 ثوانٍ | 0.5-1 ثانية | 5-10 مرات |
|
||||
| تضمينات الصفوف (100 نص) | 10-20 ثانية | 1-2 ثانية | 5-10 مرات |
|
||||
| استيعاب المستندات (1000 جزء) | 100-200 ثانية | 10-30 ثانية | 5-10 مرات |
|
||||
|
||||
### معلمات التكوين
|
||||
|
||||
```python
|
||||
# Recommended defaults
|
||||
DEFAULT_BATCH_SIZE = 32
|
||||
MAX_BATCH_SIZE = 128
|
||||
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
||||
```
|
||||
|
||||
## استراتيجية الاختبار
|
||||
|
||||
### اختبار الوحدات
|
||||
تضمين نص واحد (التوافق مع الإصدارات السابقة)
|
||||
معالجة الدُفعات الفارغة
|
||||
فرض الحد الأقصى لحجم الدفعة
|
||||
معالجة الأخطاء في حالة فشل بعض عناصر الدفعة
|
||||
|
||||
### اختبار التكامل
|
||||
تضمين الدُفعات من البداية إلى النهاية عبر Pulsar
|
||||
معالجة الدُفعات لخدمة تضمينات الرسم البياني
|
||||
معالجة الدُفعات لخدمة تضمينات الصفوف
|
||||
نقطة نهاية الدُفعات لبوابة واجهة برمجة التطبيقات
|
||||
|
||||
### اختبار الأداء
|
||||
قياس الإنتاجية الفردية مقابل الإنتاجية عند استخدام الدُفعات
|
||||
استخدام الذاكرة تحت أحجام دفعات مختلفة
|
||||
تحليل توزيع زمن الاستجابة
|
||||
|
||||
## خطة الترحيل
|
||||
|
||||
هذا إصدار يتضمن تغييرات جذرية. يتم تنفيذ جميع المراحل معًا.
|
||||
|
||||
### المرحلة الأولى: تغييرات المخطط
|
||||
استبدال `text: str` بـ `texts: list[str]` في EmbeddingsRequest
|
||||
تغيير نوع `vectors` إلى `list[list[list[float]]]` في EmbeddingsResponse
|
||||
|
||||
### المرحلة الثانية: تحديثات المعالج
|
||||
تحديث توقيع `on_embeddings` في معالجات FastEmbed و Ollama
|
||||
معالجة الدفعة بأكملها في استدعاء واحد للنموذج
|
||||
|
||||
### المرحلة الثالثة: تحديثات العميل
|
||||
تحديث `EmbeddingsClient.embed()` لقبول `texts: list[str]`
|
||||
|
||||
### المرحلة الرابعة: تحديثات المستخدم
|
||||
تحديث graph_embeddings لمعالجة سياقات الكيانات على شكل دفعات
|
||||
تحديث row_embeddings لمعالجة نصوص الفهرس على شكل دفعات
|
||||
تحديث document_embeddings لاستخدام المخطط الجديد
|
||||
تحديث أداة سطر الأوامر
|
||||
|
||||
### المرحلة الخامسة: بوابة واجهة برمجة التطبيقات
|
||||
تحديث نقطة نهاية تضمين للمخطط الجديد
|
||||
|
||||
### المرحلة السادسة: حزمة تطوير البرمجيات بلغة بايثون
|
||||
تحديث توقيع `FlowInstance.embeddings()`
|
||||
تحديث توقيع `SocketFlowInstance.embeddings()`
|
||||
|
||||
## أسئلة مفتوحة
|
||||
|
||||
**معالجة الدُفعات الكبيرة جدًا**: هل يجب أن ندعم إرجاع النتائج على شكل دفعات صغيرة جدًا للدُفعات الكبيرة جدًا (أكثر من 100 نص)؟
|
||||
**القيود الخاصة بالمزودين**: كيف يجب أن نتعامل مع المزودين الذين لديهم أحجام دفعات قصوى مختلفة؟
|
||||
**معالجة حالات الفشل الجزئية**: إذا فشل أحد النصوص في الدفعة، فهل يجب أن نفشل الدفعة بأكملها أم أن نرجع النتائج الجزئية؟
|
||||
**تجميع تضمينات المستندات**: هل يجب أن نقوم بتجميع البيانات عبر رسائل Chunk متعددة أم أن نحافظ على المعالجة لكل رسالة؟
|
||||
|
||||
## المراجع
|
||||
|
||||
[وثائق FastEmbed](https://github.com/qdrant/fastembed)
|
||||
[واجهة برمجة تطبيقات Ollama Embeddings](https://github.com/ollama/ollama)
|
||||
[تنفيذ EmbeddingsService](trustgraph-base/trustgraph/base/embeddings_service.py)
|
||||
[تحسين أداء GraphRAG](graphrag-performance-optimization.md)
|
||||
675
docs/tech-specs/embeddings-batch-processing.es.md
Normal file
675
docs/tech-specs/embeddings-batch-processing.es.md
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificación Técnica del Procesamiento por Lotes de Embeddings"
|
||||
parent: "Spanish (Beta)"
|
||||
---
|
||||
|
||||
# Especificación Técnica del Procesamiento por Lotes de Embeddings
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Resumen
|
||||
|
||||
Esta especificación describe optimizaciones para el servicio de embeddings para soportar el procesamiento por lotes de múltiples textos en una sola solicitud. La implementación actual procesa un texto a la vez, perdiendo las significativas ventajas de rendimiento que los modelos de embeddings proporcionan al procesar lotes.
|
||||
|
||||
1. **Ineficiencia en el Procesamiento de un Solo Texto**: La implementación actual envuelve textos individuales en una lista, lo que no aprovecha las capacidades de procesamiento por lotes de FastEmbed.
|
||||
2. **Sobrecarga de una Solicitud por Texto**: Cada texto requiere un viaje de ida y vuelta separado de Pulsar.
|
||||
3. **Ineficiencia en la Inferencia del Modelo**: Los modelos de embeddings tienen una sobrecarga fija por lote; los lotes pequeños desperdician recursos de GPU/CPU.
|
||||
4. **Procesamiento Serial en los Llamadores**: Los servicios clave iteran sobre los elementos y llaman a los embeddings uno a la vez.
|
||||
|
||||
## Objetivos
|
||||
|
||||
**Soporte para la API de Lotes**: Permitir el procesamiento de múltiples textos en una sola solicitud.
|
||||
**Compatibilidad con Versiones Anteriores**: Mantener el soporte para solicitudes de un solo texto.
|
||||
**Mejora Significativa del Rendimiento**: Apuntar a una mejora de rendimiento de 5 a 10 veces para operaciones por lotes.
|
||||
**Latencia Reducida por Texto**: Disminuir la latencia amortizada al incrustar múltiples textos.
|
||||
**Eficiencia de Memoria**: Procesar lotes sin un consumo excesivo de memoria.
|
||||
**Independencia del Proveedor**: Soporte para el procesamiento por lotes en FastEmbed, Ollama y otros proveedores.
|
||||
**Migración de Llamadores**: Actualizar todos los llamadores de embeddings para que utilicen la API de lotes cuando sea beneficioso.
|
||||
|
||||
## Antecedentes
|
||||
|
||||
### Implementación Actual - Servicio de Embeddings
|
||||
|
||||
La implementación de embeddings en `trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` presenta una ineficiencia de rendimiento significativa:
|
||||
|
||||
```python
|
||||
# fastembed/processor.py line 56
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
vecs = self.embeddings.embed([text]) # Single text wrapped in list
|
||||
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**Problemas:**
|
||||
|
||||
1. **Tamaño de lote 1**: El método `embed()` de FastEmbed está optimizado para el procesamiento por lotes, pero siempre lo llamamos con `[text]`, un lote de tamaño 1.
|
||||
|
||||
2. **Sobrecarga por solicitud**: Cada solicitud de incrustación incurre en:
|
||||
Serialización/deserialización de mensajes de Pulsar
|
||||
Latencia de ida y vuelta de la red
|
||||
Sobrecarga de inicio de inferencia del modelo
|
||||
Sobrecarga de programación asíncrona de Python
|
||||
|
||||
3. **Limitación del esquema**: El esquema `EmbeddingsRequest` solo admite un texto:
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
text: str = "" # Single text only
|
||||
```
|
||||
|
||||
### Llamadores actuales - Procesamiento serial
|
||||
|
||||
#### 1. API Gateway
|
||||
|
||||
**Archivo:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
La puerta de enlace acepta solicitudes de incrustación de texto único a través de HTTP/WebSocket y las reenvía al servicio de incrustaciones. Actualmente no existe un punto final por lotes.
|
||||
|
||||
```python
|
||||
class EmbeddingsRequestor(ServiceRequestor):
|
||||
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
||||
request_schema=EmbeddingsRequest, # Single text only
|
||||
response_schema=EmbeddingsResponse,
|
||||
```
|
||||
|
||||
**Impacto:** Los clientes externos (aplicaciones web, scripts) deben realizar N solicitudes HTTP para incrustar N textos.
|
||||
|
||||
#### 2. Servicio de Incorporación de Documentos
|
||||
|
||||
**Archivo:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
Procesa fragmentos de documentos uno a la vez:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
v = msg.value()
|
||||
|
||||
# Single chunk per request
|
||||
resp = await flow("embeddings-request").request(
|
||||
EmbeddingsRequest(text=v.chunk)
|
||||
)
|
||||
vectors = resp.vectors
|
||||
```
|
||||
|
||||
**Impacto:** Cada fragmento de documento requiere una llamada de incrustación separada. Un documento con 100 fragmentos = 100 solicitudes de incrustación.
|
||||
|
||||
#### 3. Servicio de Incrustaciones de Grafos
|
||||
|
||||
**Archivo:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
|
||||
Recorre las entidades e incrusta cada una de forma secuencial:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for entity in v.entities:
|
||||
# Serial embedding - one entity at a time
|
||||
vectors = await flow("embeddings-request").embed(
|
||||
text=entity.context
|
||||
)
|
||||
entities.append(EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors,
|
||||
chunk_id=entity.chunk_id,
|
||||
))
|
||||
```
|
||||
|
||||
**Impacto:** Un mensaje con 50 entidades = 50 solicitudes de incrustación serial. Esto es un cuello de botella importante durante la construcción del grafo de conocimiento.
|
||||
|
||||
#### 4. Servicio de Incrustaciones de Filas
|
||||
|
||||
**Archivo:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
|
||||
Itera sobre textos únicos e incrusta cada uno de forma serial:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
# Serial embedding - one text at a time
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
|
||||
embeddings_list.append(RowIndexEmbedding(
|
||||
index_name=index_name,
|
||||
index_value=index_value,
|
||||
text=text,
|
||||
vectors=vectors
|
||||
))
|
||||
```
|
||||
|
||||
**Impacto:** Procesar una tabla con 100 valores indexados únicos = 100 solicitudes de incrustación seriales.
|
||||
|
||||
#### 5. EmbeddingsClient (Cliente Base)
|
||||
|
||||
**Archivo:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
El cliente utilizado por todos los procesadores de flujo solo admite la incrustación de texto único:
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(self, text, timeout=30):
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(text=text), # Single text
|
||||
timeout=timeout
|
||||
)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
**Impacto:** Todos los clientes que utilizan esta herramienta están limitados a operaciones de texto único.
|
||||
|
||||
#### 6. Herramientas de Línea de Comandos
|
||||
|
||||
**Archivo:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
La herramienta de la línea de comandos acepta un único argumento de texto:
|
||||
|
||||
```python
|
||||
def query(url, flow_id, text, token=None):
|
||||
result = flow.embeddings(text=text) # Single text
|
||||
vectors = result.get("vectors", [])
|
||||
```
|
||||
|
||||
**Impacto:** Los usuarios no pueden realizar incrustaciones por lotes desde la línea de comandos. El procesamiento de un archivo de textos requiere N invocaciones.
|
||||
|
||||
#### 7. SDK de Python
|
||||
|
||||
El SDK de Python proporciona dos clases de cliente para interactuar con los servicios de TrustGraph. Ambas solo admiten la incrustación de un solo texto.
|
||||
|
||||
**Archivo:** `trustgraph-base/trustgraph/api/flow.py`
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, text):
|
||||
"""Get embeddings for a single text"""
|
||||
input = {"text": text}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**Archivo:** `trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, text: str, **kwargs: Any) -> Dict[str, Any]:
|
||||
"""Get embeddings for a single text via WebSocket"""
|
||||
request = {"text": text}
|
||||
return self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
```
|
||||
|
||||
**Impacto:** Los desarrolladores de Python que utilizan el SDK deben iterar sobre los textos y realizar N llamadas de API separadas. No existe soporte para la inserción por lotes para los usuarios del SDK.
|
||||
|
||||
### Impacto en el rendimiento
|
||||
|
||||
Para la ingestión típica de documentos (1000 fragmentos de texto):
|
||||
**Actual:** 1000 solicitudes separadas, 1000 llamadas de inferencia de modelos.
|
||||
**Por lotes (batch_size=32):** 32 solicitudes, 32 llamadas de inferencia de modelos (reducción del 96.8%).
|
||||
|
||||
Para la inserción de gráficos (mensaje con 50 entidades):
|
||||
**Actual:** 50 llamadas `await` secuenciales, ~5-10 segundos.
|
||||
**Por lotes:** 1-2 llamadas por lotes, ~0.5-1 segundo (mejora de 5-10 veces).
|
||||
|
||||
FastEmbed y bibliotecas similares logran una escalabilidad de rendimiento cercana a la lineal con el tamaño del lote hasta los límites del hardware (típicamente 32-128 textos por lote).
|
||||
|
||||
## Diseño técnico
|
||||
|
||||
### Arquitectura
|
||||
|
||||
La optimización del procesamiento por lotes de inserciones requiere cambios en los siguientes componentes:
|
||||
|
||||
#### 1. **Mejora del esquema**
|
||||
Extender `EmbeddingsRequest` para admitir múltiples textos.
|
||||
Extender `EmbeddingsResponse` para devolver múltiples conjuntos de vectores.
|
||||
Mantener la compatibilidad con versiones anteriores con solicitudes de un solo texto.
|
||||
|
||||
Módulo: `trustgraph-base/trustgraph/schema/services/llm.py`
|
||||
|
||||
#### 2. **Mejora del servicio base**
|
||||
Actualizar `EmbeddingsService` para manejar solicitudes por lotes.
|
||||
Agregar configuración del tamaño del lote.
|
||||
Implementar el manejo de solicitudes con conocimiento del lote.
|
||||
|
||||
Módulo: `trustgraph-base/trustgraph/base/embeddings_service.py`
|
||||
|
||||
#### 3. **Actualizaciones del procesador del proveedor**
|
||||
Actualizar el procesador FastEmbed para pasar el lote completo a `embed()`.
|
||||
Actualizar el procesador de Ollama para manejar lotes (si es compatible).
|
||||
Agregar procesamiento secuencial de respaldo para los proveedores que no admiten lotes.
|
||||
|
||||
Módulos:
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
||||
|
||||
#### 4. **Mejora del cliente**
|
||||
Agregar un método de inserción por lotes a `EmbeddingsClient`.
|
||||
Admitir tanto API individuales como por lotes.
|
||||
Agregar inserción automática por lotes para grandes entradas.
|
||||
|
||||
Módulo: `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
#### 5. **Actualizaciones del llamador: Procesadores de flujo**
|
||||
Actualizar `graph_embeddings` para agrupar los contextos de las entidades.
|
||||
Actualizar `row_embeddings` para agrupar los textos del índice.
|
||||
Actualizar `document_embeddings` si el agrupamiento de mensajes es factible.
|
||||
|
||||
Módulos:
|
||||
`trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
#### 6. **Mejora de la puerta de enlace de API**
|
||||
Agregar un punto final de inserción por lotes.
|
||||
Admitir una matriz de textos en el cuerpo de la solicitud.
|
||||
|
||||
Módulo: `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
#### 7. **Mejora de la herramienta de la línea de comandos**
|
||||
Agregar soporte para múltiples textos o entrada de archivos.
|
||||
Agregar un parámetro de tamaño de lote.
|
||||
|
||||
Módulo: `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
#### 8. **Mejora del SDK de Python**
|
||||
Agregar el método `embeddings_batch()` a `FlowInstance`.
|
||||
Agregar el método `embeddings_batch()` a `SocketFlowInstance`.
|
||||
Admitir tanto API individuales como por lotes para los usuarios del SDK.
|
||||
|
||||
Módulos:
|
||||
`trustgraph-base/trustgraph/api/flow.py`
|
||||
`trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
### Modelos de datos
|
||||
|
||||
#### EmbeddingsRequest
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Uso:
|
||||
Texto único: `EmbeddingsRequest(texts=["hello world"])`
|
||||
Lote: `EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
||||
|
||||
#### EmbeddingsResponse
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Estructura de la respuesta:
|
||||
`vectors[i]` contiene el conjunto de vectores para `texts[i]`
|
||||
Cada conjunto de vectores es `list[list[float]]` (los modelos pueden devolver múltiples vectores por texto)
|
||||
Ejemplo: 3 textos → `vectors` tiene 3 entradas, cada una conteniendo los incrustados de ese texto
|
||||
|
||||
### APIs
|
||||
|
||||
#### EmbeddingsClient
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(
|
||||
self,
|
||||
texts: list[str],
|
||||
timeout: float = 300,
|
||||
) -> list[list[list[float]]]:
|
||||
"""
|
||||
Embed one or more texts in a single request.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
timeout: Timeout for the operation
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(texts=texts),
|
||||
timeout=timeout
|
||||
)
|
||||
if resp.error:
|
||||
raise RuntimeError(resp.error.message)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
#### Punto final de incrustaciones de la API Gateway
|
||||
|
||||
Punto final actualizado que admite incrustaciones individuales o por lotes:
|
||||
|
||||
```
|
||||
POST /api/v1/embeddings
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"texts": ["text1", "text2", "text3"],
|
||||
"flow_id": "default"
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"vectors": [
|
||||
[[0.1, 0.2, ...]],
|
||||
[[0.3, 0.4, ...]],
|
||||
[[0.5, 0.6, ...]]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Detalles de implementación
|
||||
|
||||
#### Fase 1: Cambios en el esquema
|
||||
|
||||
**EmbeddingsRequest:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**Respuesta de Inserción:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**Actualizaciones en EmbeddingsService.on_request:**
|
||||
```python
|
||||
async def on_request(self, msg, consumer, flow):
|
||||
request = msg.value()
|
||||
id = msg.properties()["id"]
|
||||
model = flow("model")
|
||||
|
||||
vectors = await self.on_embeddings(request.texts, model=model)
|
||||
response = EmbeddingsResponse(error=None, vectors=vectors)
|
||||
|
||||
await flow("response").send(response, properties={"id": id})
|
||||
```
|
||||
|
||||
#### Fase 2: Actualización del Procesador FastEmbed
|
||||
|
||||
**Actual (Ineficiente):**
|
||||
```python
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
vecs = self.embeddings.embed([text]) # Batch of 1
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**Actualizado:**
|
||||
```python
|
||||
async def on_embeddings(self, texts: list[str], model=None):
|
||||
"""Embed texts - processes all texts in single model call"""
|
||||
if not texts:
|
||||
return []
|
||||
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
# FastEmbed handles the full batch efficiently
|
||||
all_vecs = list(self.embeddings.embed(texts))
|
||||
|
||||
# Return list of vector sets, one per input text
|
||||
return [[v.tolist()] for v in all_vecs]
|
||||
```
|
||||
|
||||
#### Fase 3: Actualización del Servicio de Inserción de Gráficos
|
||||
|
||||
**Actual (Serial):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
entities = []
|
||||
for entity in v.entities:
|
||||
vectors = await flow("embeddings-request").embed(text=entity.context)
|
||||
entities.append(EntityEmbeddings(...))
|
||||
```
|
||||
|
||||
**Actualizado (Lote):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
# Collect all contexts
|
||||
contexts = [entity.context for entity in v.entities]
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=contexts)
|
||||
|
||||
# Pair results with entities
|
||||
entities = [
|
||||
EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors[0], # First vector from the set
|
||||
chunk_id=entity.chunk_id,
|
||||
)
|
||||
for entity, vectors in zip(v.entities, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### Fase 4: Actualización del Servicio de Incrustación de Filas
|
||||
|
||||
**Actual (Serial):**
|
||||
```python
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
embeddings_list.append(RowIndexEmbedding(...))
|
||||
```
|
||||
|
||||
**Actualizado (Lote):**
|
||||
```python
|
||||
# Collect texts and metadata
|
||||
texts = list(texts_to_embed.keys())
|
||||
metadata = list(texts_to_embed.values())
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=texts)
|
||||
|
||||
# Pair results
|
||||
embeddings_list = [
|
||||
RowIndexEmbedding(
|
||||
index_name=meta[0],
|
||||
index_value=meta[1],
|
||||
text=text,
|
||||
vectors=vectors[0] # First vector from the set
|
||||
)
|
||||
for text, meta, vectors in zip(texts, metadata, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### Fase 5: Mejora de la Herramienta de Línea de Comandos (CLI)
|
||||
|
||||
**CLI Actualizada:**
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(...)
|
||||
|
||||
parser.add_argument(
|
||||
'text',
|
||||
nargs='*', # Zero or more texts
|
||||
help='Text(s) to convert to embedding vectors',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--file',
|
||||
help='File containing texts (one per line)',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--batch-size',
|
||||
type=int,
|
||||
default=32,
|
||||
help='Batch size for processing (default: 32)',
|
||||
)
|
||||
```
|
||||
|
||||
Uso:
|
||||
```bash
|
||||
# Single text (existing)
|
||||
tg-invoke-embeddings "hello world"
|
||||
|
||||
# Multiple texts
|
||||
tg-invoke-embeddings "text one" "text two" "text three"
|
||||
|
||||
# From file
|
||||
tg-invoke-embeddings -f texts.txt --batch-size 64
|
||||
```
|
||||
|
||||
#### Fase 6: Mejora del SDK de Python
|
||||
|
||||
**FlowInstance (cliente HTTP):**
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, texts: list[str]) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
input = {"texts": texts}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**SocketFlowInstance (cliente WebSocket):**
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts via WebSocket.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
request = {"texts": texts}
|
||||
response = self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
return response["vectors"]
|
||||
```
|
||||
|
||||
**Ejemplos de uso del SDK:**
|
||||
|
||||
```python
|
||||
# Single text
|
||||
vectors = flow.embeddings(["hello world"])
|
||||
print(f"Dimensions: {len(vectors[0][0])}")
|
||||
|
||||
# Batch embedding
|
||||
texts = ["text one", "text two", "text three"]
|
||||
all_vectors = flow.embeddings(texts)
|
||||
|
||||
# Process results
|
||||
for text, vecs in zip(texts, all_vectors):
|
||||
print(f"{text}: {len(vecs[0])} dimensions")
|
||||
```
|
||||
|
||||
## Consideraciones de seguridad
|
||||
|
||||
**Límites de tamaño de la solicitud**: Aplicar un tamaño máximo de lote para evitar el agotamiento de recursos.
|
||||
**Manejo de tiempos de espera**: Ajustar los tiempos de espera de manera adecuada para el tamaño del lote.
|
||||
**Límites de memoria**: Monitorear el uso de memoria para lotes grandes.
|
||||
**Validación de entrada**: Validar todos los textos en el lote antes de procesarlos.
|
||||
|
||||
## Consideraciones de rendimiento
|
||||
|
||||
### Mejoras esperadas
|
||||
|
||||
**Rendimiento:**
|
||||
Texto único: ~10-50 textos/segundo (dependiendo del modelo)
|
||||
Lote (tamaño 32): ~200-500 textos/segundo (mejora de 5 a 10 veces)
|
||||
|
||||
**Latencia por texto:**
|
||||
Texto único: 50-200 ms por texto
|
||||
Lote (tamaño 32): 5-20 ms por texto (promedio)
|
||||
|
||||
**Mejoras específicas del servicio:**
|
||||
|
||||
| Servicio | Actual | En lote | Mejora |
|
||||
|---------|---------|---------|-------------|
|
||||
| Incrustaciones de grafos (50 entidades) | 5-10 s | 0.5-1 s | 5-10 veces |
|
||||
| Incrustaciones de filas (100 textos) | 10-20 s | 1-2 s | 5-10 veces |
|
||||
| Ingestión de documentos (1000 fragmentos) | 100-200 s | 10-30 s | 5-10 veces |
|
||||
|
||||
### Parámetros de configuración
|
||||
|
||||
```python
|
||||
# Recommended defaults
|
||||
DEFAULT_BATCH_SIZE = 32
|
||||
MAX_BATCH_SIZE = 128
|
||||
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
||||
```
|
||||
|
||||
## Estrategia de Pruebas
|
||||
|
||||
### Pruebas Unitarias
|
||||
Inserción de texto única (compatibilidad con versiones anteriores)
|
||||
Manejo de lotes vacíos
|
||||
Aplicación del tamaño máximo del lote
|
||||
Manejo de errores para fallas parciales del lote
|
||||
|
||||
### Pruebas de Integración
|
||||
Inserción de lote de extremo a extremo a través de Pulsar
|
||||
Procesamiento por lotes del servicio de inserción de gráficos
|
||||
Procesamiento por lotes del servicio de inserción de filas
|
||||
Punto final de lote de la puerta de enlace de la API
|
||||
|
||||
### Pruebas de Rendimiento
|
||||
Comparación de rendimiento de inserción única frente a inserción por lotes
|
||||
Uso de memoria con varios tamaños de lote
|
||||
Análisis de la distribución de la latencia
|
||||
|
||||
## Plan de Migración
|
||||
|
||||
Esta es una versión que introduce cambios importantes. Todas las fases se implementan juntas.
|
||||
|
||||
### Fase 1: Cambios en el Esquema
|
||||
Reemplazar `text: str` con `texts: list[str]` en EmbeddingsRequest
|
||||
Cambiar el tipo de `vectors` a `list[list[list[float]]]` en EmbeddingsResponse
|
||||
|
||||
### Fase 2: Actualizaciones del Procesador
|
||||
Actualizar la firma de `on_embeddings` en los procesadores FastEmbed y Ollama
|
||||
Procesar el lote completo en una única llamada al modelo
|
||||
|
||||
### Fase 3: Actualizaciones del Cliente
|
||||
Actualizar `EmbeddingsClient.embed()` para que acepte `texts: list[str]`
|
||||
|
||||
### Fase 4: Actualizaciones del Llamador
|
||||
Actualizar graph_embeddings para procesar contextos de entidades por lotes
|
||||
Actualizar row_embeddings para procesar textos de índice por lotes
|
||||
Actualizar document_embeddings para usar el nuevo esquema
|
||||
Actualizar la herramienta de línea de comandos
|
||||
|
||||
### Fase 5: Puerta de Enlace de la API
|
||||
Actualizar el punto final de inserción para el nuevo esquema
|
||||
|
||||
### Fase 6: SDK de Python
|
||||
Actualizar la firma de `FlowInstance.embeddings()`
|
||||
Actualizar la firma de `SocketFlowInstance.embeddings()`
|
||||
|
||||
## Preguntas Abiertas
|
||||
|
||||
**Inserción de Lotes Grandes en Streaming**: ¿Debemos admitir la transmisión de resultados para lotes muy grandes (>100 textos)?
|
||||
**Límites Específicos del Proveedor**: ¿Cómo debemos manejar los proveedores con tamaños máximos de lote diferentes?
|
||||
**Manejo de Fallas Parciales**: Si un texto en un lote falla, ¿deberíamos fallar todo el lote o devolver resultados parciales?
|
||||
**Inserción por Lotes de Documentos**: ¿Debemos realizar la inserción por lotes en varios mensajes de Chunk o mantener el procesamiento por mensaje?
|
||||
|
||||
## Referencias
|
||||
|
||||
[Documentación de FastEmbed](https://github.com/qdrant/fastembed)
|
||||
[API de Inserción de Ollama](https://github.com/ollama/ollama)
|
||||
[Implementación del Servicio de Inserción](trustgraph-base/trustgraph/base/embeddings_service.py)
|
||||
[Optimización del Rendimiento de GraphRAG](graphrag-performance-optimization.md)
|
||||
675
docs/tech-specs/embeddings-batch-processing.he.md
Normal file
675
docs/tech-specs/embeddings-batch-processing.he.md
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
---
|
||||
layout: default
|
||||
title: "מפרט טכני לעיבוד אצווה של הטמעות (Embeddings)"
|
||||
parent: "Hebrew (Beta)"
|
||||
---
|
||||
|
||||
# מפרט טכני לעיבוד אצווה של הטמעות (Embeddings)
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## סקירה כללית
|
||||
|
||||
מפרט זה מתאר אופטימיזציות עבור שירות ההטמעות כדי לתמוך בעיבוד אצווה של מספר טקסטים בבקשה אחת. היישום הנוכחי מעבד טקסט אחד בכל פעם, ואינו מנצל את היתרונות המשמעותיים בביצועים שמודלי הטמעה מספקים בעת עיבוד אצוות.
|
||||
|
||||
1. **חוסר יעילות בעיבוד טקסט בודד**: היישום הנוכחי עוטף טקסטים בודדים ברשימה, ובכך אינו מנצל את יכולות האצווה של FastEmbed.
|
||||
2. **תקורה של בקשה לטקסט**: כל טקסט דורש הודעת Pulsar נפרדת הלוך ושוב.
|
||||
3. **חוסר יעילות בהסקת מודל**: למודלי הטמעה יש תקורה קבועה לכל אצווה; אצוות קטנות מבזבזות משאבי GPU/CPU.
|
||||
4. **עיבוד סדרתי בלקוחות**: שירותים מרכזיים עוברים בלולאה על פריטים וקוראים להטמעות אחד בכל פעם.
|
||||
|
||||
## מטרות
|
||||
|
||||
**תמיכה בממשק API לאצוות**: לאפשר עיבוד של מספר טקסטים בבקשה אחת.
|
||||
**תאימות לאחור**: לשמור על תמיכה בבקשות לטקסט בודד.
|
||||
**שיפור משמעותי בביצועים**: לכוון לשיפור של 5-10x בביצועים עבור פעולות אצווה.
|
||||
**הפחתת השהייה לטקסט**: להוריד את ההשהייה הממוצעת בעת הטמעת מספר טקסטים.
|
||||
**יעילות בשימוש בזיכרון**: לעבד אצוות מבלי לצרוך כמות מוגזמת של זיכרון.
|
||||
**אי-תלות בספק**: לתמוך באצוות בין FastEmbed, Ollama וספקים אחרים.
|
||||
**מעבר של לקוחות**: לעדכן את כל לקוחות ההטמעות כדי להשתמש בממשק ה-API לאצוות כאשר זה מועיל.
|
||||
|
||||
## רקע
|
||||
|
||||
### יישום נוכחי - שירות הטמעות
|
||||
|
||||
היישום של ההטמעות ב-`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` מציג חוסר יעילות משמעותי בביצועים:
|
||||
|
||||
```python
|
||||
# fastembed/processor.py line 56
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
vecs = self.embeddings.embed([text]) # Single text wrapped in list
|
||||
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**בעיות:**
|
||||
|
||||
1. **גודל אצווה 1**: השיטה `embed()` של FastEmbed מותאמת לעיבוד באצווה, אך אנו תמיד משתמשים בה עם `[text]` - אצווה בגודל 1.
|
||||
|
||||
2. **תקורה לכל בקשה:** כל בקשת הטמעה כרוכה ב:
|
||||
סריאליזציה/דה-סריאליזציה של הודעת Pulsar
|
||||
השהייה של תקשורת רשת
|
||||
תקורה של אתחול הסקה של המודל
|
||||
תקורה של תזמון אסינכרוני של Python
|
||||
|
||||
3. **מגבלת סכימה:** הסכימה `EmbeddingsRequest` תומכת רק בטקסט אחד:
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
text: str = "" # Single text only
|
||||
```
|
||||
|
||||
### לקוחות נוכחיים - עיבוד סדרתי
|
||||
|
||||
#### 1. שער API
|
||||
|
||||
**קובץ:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
השער מקבל בקשות להטמעה של טקסט בודד באמצעות HTTP/WebSocket ומעביר אותן לשירות ההטמעה. כרגע אין נקודת קצה לעיבוד אצווה.
|
||||
|
||||
```python
|
||||
class EmbeddingsRequestor(ServiceRequestor):
|
||||
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
||||
request_schema=EmbeddingsRequest, # Single text only
|
||||
response_schema=EmbeddingsResponse,
|
||||
```
|
||||
|
||||
**השפעה:** לקוחות חיצוניים (אפליקציות אינטרנט, סקריפטים) חייבים לבצע N בקשות HTTP כדי להטמיע N טקסטים.
|
||||
|
||||
#### 2. שירות הטמעת מסמכים
|
||||
|
||||
**קובץ:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
מעבד פיסות של מסמכים אחת בכל פעם:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
v = msg.value()
|
||||
|
||||
# Single chunk per request
|
||||
resp = await flow("embeddings-request").request(
|
||||
EmbeddingsRequest(text=v.chunk)
|
||||
)
|
||||
vectors = resp.vectors
|
||||
```
|
||||
|
||||
**השפעה:** כל חלק במסמך דורש קריאת הטמעה נפרדת. מסמך עם 100 חלקים = 100 בקשות הטמעה.
|
||||
|
||||
#### 3. שירות הטמעת גרפים
|
||||
|
||||
**קובץ:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
|
||||
עובר בלולאה על ישויות ומטמיע כל אחת בנפרד:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for entity in v.entities:
|
||||
# Serial embedding - one entity at a time
|
||||
vectors = await flow("embeddings-request").embed(
|
||||
text=entity.context
|
||||
)
|
||||
entities.append(EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors,
|
||||
chunk_id=entity.chunk_id,
|
||||
))
|
||||
```
|
||||
|
||||
**השפעה:** הודעה עם 50 ישויות = 50 בקשות הטמעה סדרתיות. זהו צוואר בקבוק משמעותי במהלך בניית גרף ידע.
|
||||
|
||||
#### 4. שירות הטמעת שורות
|
||||
|
||||
**קובץ:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
|
||||
חוזר על טקסטים ייחודיים ומטמיע כל אחד מהם באופן סדרתי:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
# Serial embedding - one text at a time
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
|
||||
embeddings_list.append(RowIndexEmbedding(
|
||||
index_name=index_name,
|
||||
index_value=index_value,
|
||||
text=text,
|
||||
vectors=vectors
|
||||
))
|
||||
```
|
||||
|
||||
**השפעה:** עיבוד טבלה עם 100 ערכים ייחודיים עם אינדקס = 100 בקשות הטמעה סדרתיות.
|
||||
|
||||
#### 5. EmbeddingsClient (לקוח בסיסי)
|
||||
|
||||
**קובץ:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
הלקוח המשמש את כל מעבדי הזרימה תומך רק בהטמעה של טקסט בודד:
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(self, text, timeout=30):
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(text=text), # Single text
|
||||
timeout=timeout
|
||||
)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
**השפעה:** כל המשתמשים בלקוח זה מוגבלים לפעולות טקסט יחידות.
|
||||
|
||||
#### 6. כלי שורת הפקודה
|
||||
|
||||
**קובץ:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
כלי שורת הפקודה מקבל ארגומנט טקסט יחיד:
|
||||
|
||||
```python
|
||||
def query(url, flow_id, text, token=None):
|
||||
result = flow.embeddings(text=text) # Single text
|
||||
vectors = result.get("vectors", [])
|
||||
```
|
||||
|
||||
**השפעה:** משתמשים אינם יכולים לבצע הטמעה אצווה משורת הפקודה. עיבוד קובץ של טקסטים דורש N הפעלות.
|
||||
|
||||
#### 7. ערכת פיתוח תוכנה (SDK) עבור Python
|
||||
|
||||
ערכת הפיתוח תוכנה עבור Python מספקת שתי מחלקות לקוח לצורך אינטראקציה עם שירותי TrustGraph. שתיהן תומכות רק בהטמעה של טקסט בודד.
|
||||
|
||||
**קובץ:** `trustgraph-base/trustgraph/api/flow.py`
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, text):
|
||||
"""Get embeddings for a single text"""
|
||||
input = {"text": text}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**קובץ:** `trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, text: str, **kwargs: Any) -> Dict[str, Any]:
|
||||
"""Get embeddings for a single text via WebSocket"""
|
||||
request = {"text": text}
|
||||
return self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
```
|
||||
|
||||
**השפעה:** מפתחי Python המשתמשים ב-SDK חייבים לעבור על הטקסטים ולבצע N קריאות API נפרדות. אין תמיכה בהטמעה באצווה עבור משתמשי ה-SDK.
|
||||
|
||||
### השפעה על הביצועים
|
||||
|
||||
עבור הכנסת מסמכים טיפוסית (1000 מקטעי טקסט):
|
||||
**נוכחי**: 1000 בקשות נפרדות, 1000 קריאות למודל
|
||||
**באצווה (batch_size=32)**: 32 בקשות, 32 קריאות למודל (הפחתה של 96.8%)
|
||||
|
||||
עבור הטמעת גרפים (הודעה עם 50 ישויות):
|
||||
**נוכחי**: 50 קריאות await סדרתיות, ~5-10 שניות
|
||||
**באצווה**: 1-2 קריאות באצווה, ~0.5-1 שניה (שיפור של 5-10x)
|
||||
|
||||
ספריות כמו FastEmbed ודומות משיגות התרחבות כמעט ליניארית של התפוקה עם גודל האצווה עד לגבולות החומרה (בדרך כלל 32-128 טקסטים לאצווה).
|
||||
|
||||
## עיצוב טכני
|
||||
|
||||
### ארכיטקטורה
|
||||
|
||||
אופטימיזציה של עיבוד אצווה להטמעות דורשת שינויים ברכיבים הבאים:
|
||||
|
||||
#### 1. **שיפור סכימה**
|
||||
הרחבת `EmbeddingsRequest` לתמיכה במספר טקסטים
|
||||
הרחבת `EmbeddingsResponse` להחזרת מספר סטים של וקטורים
|
||||
שמירה על תאימות לאחור לבקשות טקסט בודדות
|
||||
|
||||
מודול: `trustgraph-base/trustgraph/schema/services/llm.py`
|
||||
|
||||
#### 2. **שיפור שירות בסיסי**
|
||||
עדכון `EmbeddingsService` לטיפול בבקשות באצווה
|
||||
הוספת תצורת גודל אצווה
|
||||
יישום טיפול בבקשות מודע לאצווה
|
||||
|
||||
מודול: `trustgraph-base/trustgraph/base/embeddings_service.py`
|
||||
|
||||
#### 3. **עדכוני מעבד ספק**
|
||||
עדכון מעבד FastEmbed להעברת אצווה שלמה ל-`embed()`
|
||||
עדכון מעבד Ollama לטיפול באצווה (אם נתמך)
|
||||
הוספת עיבוד רציף כברירת מחדל עבור ספקים שאינם תומכים באצווה
|
||||
|
||||
מודולים:
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
||||
|
||||
#### 4. **שיפור לקוח**
|
||||
הוספת שיטה להטמעה באצווה ל-`EmbeddingsClient`
|
||||
תמיכה גם ב-API של טקסט בודד וגם ב-API של אצווה
|
||||
הוספת אצווה אוטומטית עבור קלט גדול
|
||||
|
||||
מודול: `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
#### 5. **עדכוני קוראים - מעבדי זרימה**
|
||||
עדכון `graph_embeddings` לאצווה של הקשרים של ישויות
|
||||
עדכון `row_embeddings` לאצווה של טקסטים לאינדקס
|
||||
עדכון `document_embeddings` אם אצווה של הודעות אפשרית
|
||||
|
||||
מודולים:
|
||||
`trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
#### 6. **שיפור שער API**
|
||||
הוספת נקודת קצה להטמעה באצווה
|
||||
תמיכה במערך של טקסטים בגוף הבקשה
|
||||
|
||||
מודול: `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
#### 7. **שיפור כלי שורת הפקודה**
|
||||
הוספת תמיכה במספר טקסטים או קלט של קובץ
|
||||
הוספת פרמטר גודל אצווה
|
||||
|
||||
מודול: `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
#### 8. **שיפור SDK של Python**
|
||||
הוספת שיטה `embeddings_batch()` ל-`FlowInstance`
|
||||
הוספת שיטה `embeddings_batch()` ל-`SocketFlowInstance`
|
||||
תמיכה גם ב-API של טקסט בודד וגם ב-API של אצווה עבור משתמשי SDK
|
||||
|
||||
מודולים:
|
||||
`trustgraph-base/trustgraph/api/flow.py`
|
||||
`trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
### מודלים של נתונים
|
||||
|
||||
#### EmbeddingsRequest
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
שימוש:
|
||||
טקסט בודד: `EmbeddingsRequest(texts=["hello world"])`
|
||||
אצווה: `EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
||||
|
||||
#### EmbeddingsResponse
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
מבנה התגובה:
|
||||
`vectors[i]` מכיל את קבוצת הווקטורים עבור `texts[i]`
|
||||
כל קבוצת וקטורים היא `list[list[float]]` (מודלים עשויים להחזיר מספר וקטורים עבור כל טקסט)
|
||||
דוגמה: 3 טקסטים → `vectors` מכיל 3 רשומות, כאשר כל רשומה מכילה את הטבעות של הטקסט המתאים
|
||||
|
||||
### ממשקי API
|
||||
|
||||
#### EmbeddingsClient
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(
|
||||
self,
|
||||
texts: list[str],
|
||||
timeout: float = 300,
|
||||
) -> list[list[list[float]]]:
|
||||
"""
|
||||
Embed one or more texts in a single request.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
timeout: Timeout for the operation
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(texts=texts),
|
||||
timeout=timeout
|
||||
)
|
||||
if resp.error:
|
||||
raise RuntimeError(resp.error.message)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
#### נקודת קצה של הטמעות (Embeddings) עבור שער API
|
||||
|
||||
נקודת קצה מעודכנת התומכת בהטמעה בודדת או באצווה:
|
||||
|
||||
```
|
||||
POST /api/v1/embeddings
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"texts": ["text1", "text2", "text3"],
|
||||
"flow_id": "default"
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"vectors": [
|
||||
[[0.1, 0.2, ...]],
|
||||
[[0.3, 0.4, ...]],
|
||||
[[0.5, 0.6, ...]]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### פרטי יישום
|
||||
|
||||
#### שלב 1: שינויי סכימה
|
||||
|
||||
**EmbeddingsRequest:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**תגובת הטבעה (EmbeddingsResponse):**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**עדכון של EmbeddingsService.on_request:**
|
||||
```python
|
||||
async def on_request(self, msg, consumer, flow):
|
||||
request = msg.value()
|
||||
id = msg.properties()["id"]
|
||||
model = flow("model")
|
||||
|
||||
vectors = await self.on_embeddings(request.texts, model=model)
|
||||
response = EmbeddingsResponse(error=None, vectors=vectors)
|
||||
|
||||
await flow("response").send(response, properties={"id": id})
|
||||
```
|
||||
|
||||
#### שלב 2: עדכון מעבד FastEmbed
|
||||
|
||||
**נוכחי (לא יעיל):**
|
||||
```python
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
vecs = self.embeddings.embed([text]) # Batch of 1
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**עדכון:**
|
||||
```python
|
||||
async def on_embeddings(self, texts: list[str], model=None):
|
||||
"""Embed texts - processes all texts in single model call"""
|
||||
if not texts:
|
||||
return []
|
||||
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
# FastEmbed handles the full batch efficiently
|
||||
all_vecs = list(self.embeddings.embed(texts))
|
||||
|
||||
# Return list of vector sets, one per input text
|
||||
return [[v.tolist()] for v in all_vecs]
|
||||
```
|
||||
|
||||
#### שלב 3: עדכון שירות הטמעת גרפים
|
||||
|
||||
**נוכחי (סדרתי):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
entities = []
|
||||
for entity in v.entities:
|
||||
vectors = await flow("embeddings-request").embed(text=entity.context)
|
||||
entities.append(EntityEmbeddings(...))
|
||||
```
|
||||
|
||||
**עדכון (אצווה):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
# Collect all contexts
|
||||
contexts = [entity.context for entity in v.entities]
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=contexts)
|
||||
|
||||
# Pair results with entities
|
||||
entities = [
|
||||
EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors[0], # First vector from the set
|
||||
chunk_id=entity.chunk_id,
|
||||
)
|
||||
for entity, vectors in zip(v.entities, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### שלב 4: עדכון שירות הטמעת שורות
|
||||
|
||||
**נוכחי (סדרתי):**
|
||||
```python
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
embeddings_list.append(RowIndexEmbedding(...))
|
||||
```
|
||||
|
||||
**עדכון (אצווה):**
|
||||
```python
|
||||
# Collect texts and metadata
|
||||
texts = list(texts_to_embed.keys())
|
||||
metadata = list(texts_to_embed.values())
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=texts)
|
||||
|
||||
# Pair results
|
||||
embeddings_list = [
|
||||
RowIndexEmbedding(
|
||||
index_name=meta[0],
|
||||
index_value=meta[1],
|
||||
text=text,
|
||||
vectors=vectors[0] # First vector from the set
|
||||
)
|
||||
for text, meta, vectors in zip(texts, metadata, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### שלב 5: שיפור כלי שורת הפקודה
|
||||
|
||||
**שורת פקודה מעודכנת:**
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(...)
|
||||
|
||||
parser.add_argument(
|
||||
'text',
|
||||
nargs='*', # Zero or more texts
|
||||
help='Text(s) to convert to embedding vectors',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--file',
|
||||
help='File containing texts (one per line)',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--batch-size',
|
||||
type=int,
|
||||
default=32,
|
||||
help='Batch size for processing (default: 32)',
|
||||
)
|
||||
```
|
||||
|
||||
שימוש:
|
||||
```bash
|
||||
# Single text (existing)
|
||||
tg-invoke-embeddings "hello world"
|
||||
|
||||
# Multiple texts
|
||||
tg-invoke-embeddings "text one" "text two" "text three"
|
||||
|
||||
# From file
|
||||
tg-invoke-embeddings -f texts.txt --batch-size 64
|
||||
```
|
||||
|
||||
#### שלב 6: שיפור ערכת הפיתוח של Python
|
||||
|
||||
**FlowInstance (לקוח HTTP):**
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, texts: list[str]) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
input = {"texts": texts}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**SocketFlowInstance (לקוח WebSocket):**
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts via WebSocket.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
request = {"texts": texts}
|
||||
response = self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
return response["vectors"]
|
||||
```
|
||||
|
||||
**דוגמאות לשימוש ב-SDK:**
|
||||
|
||||
```python
|
||||
# Single text
|
||||
vectors = flow.embeddings(["hello world"])
|
||||
print(f"Dimensions: {len(vectors[0][0])}")
|
||||
|
||||
# Batch embedding
|
||||
texts = ["text one", "text two", "text three"]
|
||||
all_vectors = flow.embeddings(texts)
|
||||
|
||||
# Process results
|
||||
for text, vecs in zip(texts, all_vectors):
|
||||
print(f"{text}: {len(vecs[0])} dimensions")
|
||||
```
|
||||
|
||||
## שיקולי אבטחה
|
||||
|
||||
**מגבלות גודל בקשה**: אכוף גודל מקסימלי לאצווה כדי למנוע מיצוי משאבים
|
||||
**טיפול בזמני המתנה**: התאם את זמני ההמתנה בהתאם לגודל האצווה
|
||||
**מגבלות זיכרון**: עקוב אחר השימוש בזיכרון עבור אצוות גדולות
|
||||
**אימות קלט**: אשר את כל הטקסטים באצווה לפני העיבוד
|
||||
|
||||
## שיקולי ביצועים
|
||||
|
||||
### שיפורים צפויים
|
||||
|
||||
**קצב העברה (Throughput):**
|
||||
טקסט בודד: ~10-50 טקסטים/שנייה (תלוי במודל)
|
||||
אצווה (גודל 32): ~200-500 טקסטים/שנייה (שיפור של 5-10x)
|
||||
|
||||
**זמן תגובה לטקסט:**
|
||||
טקסט בודד: 50-200ms לטקסט
|
||||
אצווה (גודל 32): 5-20ms לטקסט (ממוצע)
|
||||
|
||||
**שיפורים ספציפיים לשירות:**
|
||||
|
||||
| שירות | נוכחי | באצווה | שיפור |
|
||||
|---------|---------|---------|-------------|
|
||||
| הטמעת גרפים (50 ישויות) | 5-10 שניות | 0.5-1 שניות | 5-10x |
|
||||
| הטמעת שורות (100 טקסטים) | 10-20 שניות | 1-2 שניות | 5-10x |
|
||||
| קליטת מסמכים (1000 מקטעים) | 100-200 שניות | 10-30 שניות | 5-10x |
|
||||
|
||||
### פרמטרי תצורה
|
||||
|
||||
```python
|
||||
# Recommended defaults
|
||||
DEFAULT_BATCH_SIZE = 32
|
||||
MAX_BATCH_SIZE = 128
|
||||
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
||||
```
|
||||
|
||||
## אסטרטגיית בדיקות
|
||||
|
||||
### בדיקות יחידה
|
||||
הטמעה של טקסט בודד (תאימות לאחור)
|
||||
טיפול באצווה ריקה
|
||||
אכיפת גודל אצווה מקסימלי
|
||||
טיפול בשגיאות עבור כשלים חלקיים באצווה
|
||||
|
||||
### בדיקות אינטגרציה
|
||||
הטמעת אצווה מקצה לקצה דרך Pulsar
|
||||
עיבוד אצווה בשירות הטמעת גרפים
|
||||
עיבוד אצווה בשירות הטמעת שורות
|
||||
נקודת קצה של אצווה בשער ה-API
|
||||
|
||||
### בדיקות ביצועים
|
||||
השוואת תפוקה של הטמעה בודדת לעומת אצווה
|
||||
שימוש בזיכרון בגדלי אצווה שונים
|
||||
ניתוח התפלגות השהייה
|
||||
|
||||
## תוכנית מעבר
|
||||
|
||||
זו גרסה הכוללת שינויים משמעותיים. כל השלבים מיושמים יחד.
|
||||
|
||||
### שלב 1: שינויי סכימה
|
||||
החלפת `text: str` ב-`texts: list[str]` ב-EmbeddingsRequest
|
||||
שינוי סוג של `vectors` ל-`list[list[list[float]]]` ב-EmbeddingsResponse
|
||||
|
||||
### שלב 2: עדכוני מעבד
|
||||
עדכון חתימה של `on_embeddings` במעבדים FastEmbed ו-Ollama
|
||||
עיבוד אצווה שלמה בפעילת מודל אחת
|
||||
|
||||
### שלב 3: עדכוני לקוח
|
||||
עדכון `EmbeddingsClient.embed()` כדי לקבל `texts: list[str]`
|
||||
|
||||
### שלב 4: עדכוני משתמשים
|
||||
עדכון graph_embeddings להטמעת הקשרים של ישויות באצווה
|
||||
עדכון row_embeddings לעיבוד אצווה של טקסטים באינדקס
|
||||
עדכון document_embeddings לשימוש בסכימה החדשה
|
||||
עדכון כלי שורת הפקודה
|
||||
|
||||
### שלב 5: שער API
|
||||
עדכון נקודת קצה של הטמעה עבור סכימה חדשה
|
||||
|
||||
### שלב 6: SDK של Python
|
||||
עדכון חתימה של `FlowInstance.embeddings()`
|
||||
עדכון חתימה של `SocketFlowInstance.embeddings()`
|
||||
|
||||
## שאלות פתוחות
|
||||
|
||||
**הטמעת אצוות גדולות**: האם עלינו לתמוך בהעברת תוצאות עבור אצוות גדולות מאוד (>100 טקסטים)?
|
||||
**מגבלות ספציפיות לספק**: כיצד עלינו להתמודד עם ספקים עם גודל אצווה מקסימלי שונה?
|
||||
**טיפול בכשלים חלקיים**: אם טקסט אחד באצווה נכשל, האם עלינו לגרום לכשל באצווה כולה או להחזיר תוצאות חלקיות?
|
||||
**הטמעת מסמכים באצווה**: האם עלינו לבצע אצווה בין הודעות Chunk מרובות או לשמור על עיבוד פר-הודעה?
|
||||
|
||||
## הפניות
|
||||
|
||||
[תיעוד FastEmbed](https://github.com/qdrant/fastembed)
|
||||
[ממשק API של הטמעות Ollama](https://github.com/ollama/ollama)
|
||||
[יישום של EmbeddingsService](trustgraph-base/trustgraph/base/embeddings_service.py)
|
||||
[אופטימיזציה של ביצועים של GraphRAG](graphrag-performance-optimization.md)
|
||||
675
docs/tech-specs/embeddings-batch-processing.hi.md
Normal file
675
docs/tech-specs/embeddings-batch-processing.hi.md
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
---
|
||||
layout: default
|
||||
title: "एम्बेडिंग बैच प्रोसेसिंग तकनीकी विनिर्देश"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# एम्बेडिंग बैच प्रोसेसिंग तकनीकी विनिर्देश
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## अवलोकन
|
||||
|
||||
यह विनिर्देश एम्बेडिंग सेवा के लिए अनुकूलन का वर्णन करता है ताकि एक ही अनुरोध में कई ग्रंथों को बैच में संसाधित किया जा सके। वर्तमान कार्यान्वयन एक समय में एक पाठ को संसाधित करता है, जिससे एम्बेडिंग मॉडल द्वारा प्रदान किए जाने वाले महत्वपूर्ण प्रदर्शन लाभों का उपयोग नहीं हो पाता है जब बैचों में प्रसंस्करण किया जाता है।
|
||||
|
||||
1. **सिंगल-टेक्स्ट प्रोसेसिंग की अक्षमता**: वर्तमान कार्यान्वयन एकल ग्रंथों को एक सूची में लपेटता है, जिससे FastEmbed की बैच क्षमताओं का पूरी तरह से उपयोग नहीं हो पाता है।
|
||||
2. **प्रति-टेक्स्ट अनुरोध ओवरहेड**: प्रत्येक पाठ के लिए एक अलग पल्सर संदेश राउंड-ट्रिप की आवश्यकता होती है।
|
||||
3. **मॉडल अनुमान की अक्षमता**: एम्बेडिंग मॉडल में एक निश्चित प्रति-बैच ओवरहेड होता है; छोटे बैच GPU/CPU संसाधनों को बर्बाद करते हैं।
|
||||
4. **कॉलरों में सीरियल प्रोसेसिंग**: प्रमुख सेवाएं आइटम्स पर लूप करती हैं और एक-एक करके एम्बेडिंग को कॉल करती हैं।
|
||||
|
||||
## लक्ष्य
|
||||
|
||||
**बैच एपीआई समर्थन**: एक ही अनुरोध में कई ग्रंथों को संसाधित करने की क्षमता सक्षम करें।
|
||||
**पिछड़ा संगतता**: एकल-पाठ अनुरोधों के लिए समर्थन बनाए रखें।
|
||||
**महत्वपूर्ण थ्रूपुट सुधार**: बल्क ऑपरेशनों के लिए 5-10 गुना थ्रूपुट सुधार का लक्ष्य रखें।
|
||||
**प्रति-पाठ कम विलंबता**: कई ग्रंथों को एम्बेड करते समय औसत विलंबता को कम करें।
|
||||
**मेमोरी दक्षता**: अत्यधिक मेमोरी खपत के बिना बैचों को संसाधित करें।
|
||||
**प्रदाता-अज्ञेय**: FastEmbed, Ollama और अन्य प्रदाताओं में बैचिंग का समर्थन करें।
|
||||
**कॉलर माइग्रेशन**: सभी एम्बेडिंग कॉलरों को अपडेट करें ताकि वे जहां फायदेमंद हो वहां बैच एपीआई का उपयोग करें।
|
||||
|
||||
## पृष्ठभूमि
|
||||
|
||||
### वर्तमान कार्यान्वयन - एम्बेडिंग सेवा
|
||||
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` में एम्बेडिंग कार्यान्वयन में एक महत्वपूर्ण प्रदर्शन अक्षमता है:
|
||||
|
||||
```python
|
||||
# fastembed/processor.py line 56
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
vecs = self.embeddings.embed([text]) # Single text wrapped in list
|
||||
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**समस्याएँ:**
|
||||
|
||||
1. **बैच का आकार 1**: FastEmbed का `embed()` तरीका बैच प्रोसेसिंग के लिए अनुकूलित है, लेकिन हम हमेशा इसे `[text]` के साथ कॉल करते हैं - जो कि आकार 1 का एक बैच है।
|
||||
|
||||
2. **प्रति-अनुरोध ओवरहेड**: प्रत्येक एम्बेडिंग अनुरोध में शामिल हैं:
|
||||
पल्सर संदेश का क्रमबद्धता/विघटन
|
||||
नेटवर्क राउंड-ट्रिप विलंबता
|
||||
मॉडल अनुमान स्टार्टअप ओवरहेड
|
||||
पायथन एसिंक्रोनस शेड्यूलिंग ओवरहेड
|
||||
|
||||
3. **स्कीमा सीमा**: `EmbeddingsRequest` स्कीमा केवल एक टेक्स्ट का समर्थन करता है:
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
text: str = "" # Single text only
|
||||
```
|
||||
|
||||
### वर्तमान कॉलर - सीरियल प्रोसेसिंग
|
||||
|
||||
#### 1. एपीआई गेटवे
|
||||
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
गेटवे HTTP/WebSocket के माध्यम से सिंगल-टेक्स्ट एम्बेडिंग अनुरोध स्वीकार करता है और उन्हें एम्बेडिंग सेवा को भेजता है। वर्तमान में कोई बैच एंडपॉइंट मौजूद नहीं है।
|
||||
|
||||
```python
|
||||
class EmbeddingsRequestor(ServiceRequestor):
|
||||
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
||||
request_schema=EmbeddingsRequest, # Single text only
|
||||
response_schema=EmbeddingsResponse,
|
||||
```
|
||||
|
||||
**प्रभाव:** बाहरी क्लाइंट (वेब ऐप्स, स्क्रिप्ट) को N टेक्स्ट एम्बेड करने के लिए N HTTP अनुरोध करने होंगे।
|
||||
|
||||
#### 2. दस्तावेज़ एम्बेडिंग सेवा
|
||||
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
दस्तावेज़ के टुकड़ों को एक-एक करके संसाधित करता है:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
v = msg.value()
|
||||
|
||||
# Single chunk per request
|
||||
resp = await flow("embeddings-request").request(
|
||||
EmbeddingsRequest(text=v.chunk)
|
||||
)
|
||||
vectors = resp.vectors
|
||||
```
|
||||
|
||||
**प्रभाव:** प्रत्येक दस्तावेज़ खंड के लिए एक अलग एम्बेडिंग कॉल की आवश्यकता होती है। 100 खंडों वाला एक दस्तावेज़ = 100 एम्बेडिंग अनुरोध।
|
||||
|
||||
#### 3. ग्राफ एम्बेडिंग सेवा
|
||||
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
|
||||
यह एंटिटीज पर लूप करता है और प्रत्येक को क्रमिक रूप से एम्बेड करता है:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for entity in v.entities:
|
||||
# Serial embedding - one entity at a time
|
||||
vectors = await flow("embeddings-request").embed(
|
||||
text=entity.context
|
||||
)
|
||||
entities.append(EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors,
|
||||
chunk_id=entity.chunk_id,
|
||||
))
|
||||
```
|
||||
|
||||
**प्रभाव:** 50 एंटिटीज वाला एक संदेश = 50 सीरियल एम्बेडिंग अनुरोध। यह ज्ञान ग्राफ निर्माण के दौरान एक बड़ी बाधा है।
|
||||
|
||||
#### 4. रो एम्बेडिंग सेवा
|
||||
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
|
||||
यह अद्वितीय टेक्स्ट पर लूप करता है और प्रत्येक को क्रमिक रूप से एम्बेड करता है:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
# Serial embedding - one text at a time
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
|
||||
embeddings_list.append(RowIndexEmbedding(
|
||||
index_name=index_name,
|
||||
index_value=index_value,
|
||||
text=text,
|
||||
vectors=vectors
|
||||
))
|
||||
```
|
||||
|
||||
**प्रभाव:** 100 अद्वितीय अनुक्रमित मानों वाली तालिका को संसाधित करने से 100 सीरियल एम्बेडिंग अनुरोध उत्पन्न होते हैं।
|
||||
|
||||
#### 5. एम्बेडिंग्सक्लाइंट (बेस क्लाइंट)
|
||||
|
||||
**फ़ाइल:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
सभी फ्लो प्रोसेसर द्वारा उपयोग किए जाने वाले क्लाइंट केवल सिंगल-टेक्स्ट एम्बेडिंग का समर्थन करते हैं:
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(self, text, timeout=30):
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(text=text), # Single text
|
||||
timeout=timeout
|
||||
)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
**प्रभाव:** इस क्लाइंट का उपयोग करने वाले सभी एप्लिकेशन केवल एकल-पाठ संचालन तक सीमित हैं।
|
||||
|
||||
#### 6. कमांड-लाइन उपकरण
|
||||
|
||||
**फ़ाइल:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
कमांड-लाइन उपकरण एक एकल पाठ तर्क स्वीकार करता है:
|
||||
|
||||
```python
|
||||
def query(url, flow_id, text, token=None):
|
||||
result = flow.embeddings(text=text) # Single text
|
||||
vectors = result.get("vectors", [])
|
||||
```
|
||||
|
||||
**प्रभाव:** उपयोगकर्ता कमांड लाइन से बैच एम्बेडिंग नहीं कर सकते। टेक्स्ट फ़ाइल को संसाधित करने के लिए N बार कॉल की आवश्यकता होती है।
|
||||
|
||||
#### 7. पायथन SDK
|
||||
|
||||
पायथन SDK ट्रस्टग्राफ सेवाओं के साथ इंटरैक्ट करने के लिए दो क्लाइंट क्लास प्रदान करता है। दोनों केवल सिंगल-टेक्स्ट एम्बेडिंग का समर्थन करते हैं।
|
||||
|
||||
**फ़ाइल:** `trustgraph-base/trustgraph/api/flow.py`
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, text):
|
||||
"""Get embeddings for a single text"""
|
||||
input = {"text": text}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**फ़ाइल:** `trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, text: str, **kwargs: Any) -> Dict[str, Any]:
|
||||
"""Get embeddings for a single text via WebSocket"""
|
||||
request = {"text": text}
|
||||
return self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
```
|
||||
|
||||
**प्रभाव:** एसडीके का उपयोग करने वाले पायथन डेवलपर्स को टेक्स्ट पर लूप करना होगा और एन अलग एपीआई कॉल करने होंगे। एसडीके उपयोगकर्ताओं के लिए कोई बैच एम्बेडिंग समर्थन मौजूद नहीं है।
|
||||
|
||||
### प्रदर्शन प्रभाव
|
||||
|
||||
सामान्य दस्तावेज़ इनपुट (1000 टेक्स्ट खंड) के लिए:
|
||||
**वर्तमान:** 1000 अलग-अलग अनुरोध, 1000 मॉडल अनुमान कॉल
|
||||
**बैच (batch_size=32):** 32 अनुरोध, 32 मॉडल अनुमान कॉल (96.8% कमी)
|
||||
|
||||
ग्राफ एम्बेडिंग (50 संस्थाओं वाला संदेश) के लिए:
|
||||
**वर्तमान:** 50 सीरियल अवित कॉल, ~5-10 सेकंड
|
||||
**बैच:** 1-2 बैच कॉल, ~0.5-1 सेकंड (5-10 गुना सुधार)
|
||||
|
||||
FastEmbed और समान लाइब्रेरी हार्डवेयर सीमाओं तक बैच आकार के साथ लगभग रैखिक थ्रूपुट स्केलिंग प्राप्त करती हैं (आमतौर पर प्रति बैच 32-128 टेक्स्ट)।
|
||||
|
||||
## तकनीकी डिज़ाइन
|
||||
|
||||
### आर्किटेक्चर
|
||||
|
||||
एम्बेडिंग बैच प्रोसेसिंग अनुकूलन के लिए निम्नलिखित घटकों में परिवर्तन की आवश्यकता है:
|
||||
|
||||
#### 1. **स्कीमा संवर्धन**
|
||||
`EmbeddingsRequest` को कई टेक्स्ट का समर्थन करने के लिए विस्तारित करें
|
||||
`EmbeddingsResponse` को कई वेक्टर सेट वापस करने के लिए विस्तारित करें
|
||||
एकल-टेक्स्ट अनुरोधों के साथ पिछड़े अनुकूलता बनाए रखें
|
||||
|
||||
मॉड्यूल: `trustgraph-base/trustgraph/schema/services/llm.py`
|
||||
|
||||
#### 2. **बेस सर्विस संवर्धन**
|
||||
`EmbeddingsService` को बैच अनुरोधों को संभालने के लिए अपडेट करें
|
||||
बैच आकार कॉन्फ़िगरेशन जोड़ें
|
||||
बैच-जागरूक अनुरोध हैंडलिंग लागू करें
|
||||
|
||||
मॉड्यूल: `trustgraph-base/trustgraph/base/embeddings_service.py`
|
||||
|
||||
#### 3. **प्रदाता प्रोसेसर अपडेट**
|
||||
FastEmbed प्रोसेसर को अपडेट करें ताकि `embed()` को पूरा बैच पास किया जा सके
|
||||
यदि समर्थित है, तो बैचों को संभालने के लिए Ollama प्रोसेसर को अपडेट करें
|
||||
बैच समर्थन के बिना प्रदाताओं के लिए एक वैकल्पिक अनुक्रमिक प्रसंस्करण जोड़ें
|
||||
|
||||
मॉड्यूल:
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
||||
|
||||
#### 4. **क्लाइंट में सुधार**
|
||||
`EmbeddingsClient` में बैच एम्बेडिंग विधि जोड़ें
|
||||
सिंगल और बैच एपीआई दोनों का समर्थन करें
|
||||
बड़े इनपुट के लिए स्वचालित बैचिंग जोड़ें
|
||||
|
||||
मॉड्यूल: `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
#### 5. **कॉल करने वाले अपडेट - फ्लो प्रोसेसर**
|
||||
`graph_embeddings` को बैच एंटिटी कॉन्टेक्स्ट के लिए अपडेट करें
|
||||
`row_embeddings` को बैच इंडेक्स टेक्स्ट के लिए अपडेट करें
|
||||
यदि संदेश बैचिंग संभव है, तो `document_embeddings` को अपडेट करें
|
||||
|
||||
मॉड्यूल:
|
||||
`trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
#### 6. **एपीआई गेटवे में सुधार**
|
||||
बैच एम्बेडिंग एंडपॉइंट जोड़ें
|
||||
अनुरोध बॉडी में टेक्स्ट की सरणी का समर्थन करें
|
||||
|
||||
मॉड्यूल: `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
#### 7. **सीएलआई टूल में सुधार**
|
||||
कई टेक्स्ट या फ़ाइल इनपुट के लिए समर्थन जोड़ें
|
||||
बैच आकार पैरामीटर जोड़ें
|
||||
|
||||
मॉड्यूल: `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
#### 8. **पायथन एसडीके में सुधार**
|
||||
`FlowInstance` में `embeddings_batch()` विधि जोड़ें
|
||||
`SocketFlowInstance` में `embeddings_batch()` विधि जोड़ें
|
||||
एसडीके उपयोगकर्ताओं के लिए सिंगल और बैच एपीआई दोनों का समर्थन करें
|
||||
|
||||
मॉड्यूल:
|
||||
`trustgraph-base/trustgraph/api/flow.py`
|
||||
`trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
### डेटा मॉडल
|
||||
|
||||
#### एम्बेडिंग्स रिक्वेस्ट
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
उपयोग:
|
||||
एकल पाठ: `EmbeddingsRequest(texts=["hello world"])`
|
||||
बैच: `EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
||||
|
||||
#### एम्बेडिंग रिस्पांस
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
प्रतिक्रिया संरचना:
|
||||
`vectors[i]` में `texts[i]` के लिए वेक्टर सेट शामिल है।
|
||||
प्रत्येक वेक्टर सेट `list[list[float]]` होता है (मॉडल प्रत्येक पाठ के लिए कई वेक्टर वापस कर सकते हैं)।
|
||||
उदाहरण: 3 पाठ → `vectors` में 3 प्रविष्टियाँ हैं, जिनमें से प्रत्येक में उस पाठ के एम्बेडिंग होते हैं।
|
||||
|
||||
### एपीआई
|
||||
|
||||
#### एम्बेडिंगक्लाइंट
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(
|
||||
self,
|
||||
texts: list[str],
|
||||
timeout: float = 300,
|
||||
) -> list[list[list[float]]]:
|
||||
"""
|
||||
Embed one or more texts in a single request.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
timeout: Timeout for the operation
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(texts=texts),
|
||||
timeout=timeout
|
||||
)
|
||||
if resp.error:
|
||||
raise RuntimeError(resp.error.message)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
#### एपीआई गेटवे एम्बेडिंग एंडपॉइंट
|
||||
|
||||
अपडेटेड एंडपॉइंट जो सिंगल या बैच एम्बेडिंग को सपोर्ट करता है:
|
||||
|
||||
```
|
||||
POST /api/v1/embeddings
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"texts": ["text1", "text2", "text3"],
|
||||
"flow_id": "default"
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"vectors": [
|
||||
[[0.1, 0.2, ...]],
|
||||
[[0.3, 0.4, ...]],
|
||||
[[0.5, 0.6, ...]]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### कार्यान्वयन विवरण
|
||||
|
||||
#### चरण 1: स्कीमा परिवर्तन
|
||||
|
||||
**एम्बेडिंग रिक्वेस्ट:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**एम्बेडिंग रिस्पांस:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**अपडेटेड एम्बेडिंगसर्विस.ऑन_रिक्वेस्ट:**
|
||||
```python
|
||||
async def on_request(self, msg, consumer, flow):
|
||||
request = msg.value()
|
||||
id = msg.properties()["id"]
|
||||
model = flow("model")
|
||||
|
||||
vectors = await self.on_embeddings(request.texts, model=model)
|
||||
response = EmbeddingsResponse(error=None, vectors=vectors)
|
||||
|
||||
await flow("response").send(response, properties={"id": id})
|
||||
```
|
||||
|
||||
#### चरण 2: फास्टएम्बेड प्रोसेसर अपडेट
|
||||
|
||||
**वर्तमान (अकुशल):**
|
||||
```python
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
vecs = self.embeddings.embed([text]) # Batch of 1
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**अद्यतन:**
|
||||
```python
|
||||
async def on_embeddings(self, texts: list[str], model=None):
|
||||
"""Embed texts - processes all texts in single model call"""
|
||||
if not texts:
|
||||
return []
|
||||
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
# FastEmbed handles the full batch efficiently
|
||||
all_vecs = list(self.embeddings.embed(texts))
|
||||
|
||||
# Return list of vector sets, one per input text
|
||||
return [[v.tolist()] for v in all_vecs]
|
||||
```
|
||||
|
||||
#### चरण 3: ग्राफ एम्बेडिंग सेवा अपडेट
|
||||
|
||||
**वर्तमान (सीरियल):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
entities = []
|
||||
for entity in v.entities:
|
||||
vectors = await flow("embeddings-request").embed(text=entity.context)
|
||||
entities.append(EntityEmbeddings(...))
|
||||
```
|
||||
|
||||
**अद्यतन (बैच):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
# Collect all contexts
|
||||
contexts = [entity.context for entity in v.entities]
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=contexts)
|
||||
|
||||
# Pair results with entities
|
||||
entities = [
|
||||
EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors[0], # First vector from the set
|
||||
chunk_id=entity.chunk_id,
|
||||
)
|
||||
for entity, vectors in zip(v.entities, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### चरण 4: पंक्ति एम्बेडिंग सेवा अपडेट
|
||||
|
||||
**वर्तमान (क्रमिक):**
|
||||
```python
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
embeddings_list.append(RowIndexEmbedding(...))
|
||||
```
|
||||
|
||||
**अद्यतन (बैच):**
|
||||
```python
|
||||
# Collect texts and metadata
|
||||
texts = list(texts_to_embed.keys())
|
||||
metadata = list(texts_to_embed.values())
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=texts)
|
||||
|
||||
# Pair results
|
||||
embeddings_list = [
|
||||
RowIndexEmbedding(
|
||||
index_name=meta[0],
|
||||
index_value=meta[1],
|
||||
text=text,
|
||||
vectors=vectors[0] # First vector from the set
|
||||
)
|
||||
for text, meta, vectors in zip(texts, metadata, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### चरण 5: कमांड-लाइन टूल में सुधार
|
||||
|
||||
**अद्यतन कमांड-लाइन इंटरफ़ेस:**
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(...)
|
||||
|
||||
parser.add_argument(
|
||||
'text',
|
||||
nargs='*', # Zero or more texts
|
||||
help='Text(s) to convert to embedding vectors',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--file',
|
||||
help='File containing texts (one per line)',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--batch-size',
|
||||
type=int,
|
||||
default=32,
|
||||
help='Batch size for processing (default: 32)',
|
||||
)
|
||||
```
|
||||
|
||||
उपयोग:
|
||||
```bash
|
||||
# Single text (existing)
|
||||
tg-invoke-embeddings "hello world"
|
||||
|
||||
# Multiple texts
|
||||
tg-invoke-embeddings "text one" "text two" "text three"
|
||||
|
||||
# From file
|
||||
tg-invoke-embeddings -f texts.txt --batch-size 64
|
||||
```
|
||||
|
||||
#### चरण 6: पायथन एसडीके में सुधार
|
||||
|
||||
**फ्लोइंस्टेंस (एचटीटीपी क्लाइंट):**
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, texts: list[str]) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
input = {"texts": texts}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**सॉकेटफ्लोइंस्टेंस (वेबसोकेट क्लाइंट):**
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts via WebSocket.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
request = {"texts": texts}
|
||||
response = self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
return response["vectors"]
|
||||
```
|
||||
|
||||
**एसडीके उपयोग के उदाहरण:**
|
||||
|
||||
```python
|
||||
# Single text
|
||||
vectors = flow.embeddings(["hello world"])
|
||||
print(f"Dimensions: {len(vectors[0][0])}")
|
||||
|
||||
# Batch embedding
|
||||
texts = ["text one", "text two", "text three"]
|
||||
all_vectors = flow.embeddings(texts)
|
||||
|
||||
# Process results
|
||||
for text, vecs in zip(texts, all_vectors):
|
||||
print(f"{text}: {len(vecs[0])} dimensions")
|
||||
```
|
||||
|
||||
## सुरक्षा संबंधी विचार
|
||||
|
||||
**अनुरोध आकार सीमाएँ**: संसाधनों की कमी को रोकने के लिए अधिकतम बैच आकार लागू करें।
|
||||
**समय-सीमा प्रबंधन**: बैच आकार के लिए समय-सीमा को उचित रूप से समायोजित करें।
|
||||
**मेमोरी सीमाएँ**: बड़े बैचों के लिए मेमोरी उपयोग की निगरानी करें।
|
||||
**इनपुट सत्यापन**: प्रसंस्करण से पहले बैच में सभी पाठों को मान्य करें।
|
||||
|
||||
## प्रदर्शन संबंधी विचार
|
||||
|
||||
### अपेक्षित सुधार
|
||||
|
||||
**थ्रूपुट:**
|
||||
एकल-पाठ: ~10-50 पाठ/सेकंड (मॉडल के आधार पर)
|
||||
बैच (आकार 32): ~200-500 पाठ/सेकंड (5-10 गुना सुधार)
|
||||
|
||||
**प्रति पाठ विलंबता:**
|
||||
एकल-पाठ: प्रति पाठ 50-200ms
|
||||
बैच (आकार 32): प्रति पाठ 5-20ms (औसत)
|
||||
|
||||
**सेवा-विशिष्ट सुधार:**
|
||||
|
||||
| सेवा | वर्तमान | बैच | सुधार |
|
||||
|---------|---------|---------|-------------|
|
||||
| ग्राफ एम्बेडिंग (50 इकाइयाँ) | 5-10s | 0.5-1s | 5-10x |
|
||||
| पंक्ति एम्बेडिंग (100 पाठ) | 10-20s | 1-2s | 5-10x |
|
||||
| दस्तावेज़ इनपुट (1000 खंड) | 100-200s | 10-30s | 5-10x |
|
||||
|
||||
### कॉन्फ़िगरेशन पैरामीटर
|
||||
|
||||
```python
|
||||
# Recommended defaults
|
||||
DEFAULT_BATCH_SIZE = 32
|
||||
MAX_BATCH_SIZE = 128
|
||||
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
||||
```
|
||||
|
||||
## परीक्षण रणनीति
|
||||
|
||||
### यूनिट परीक्षण
|
||||
सिंगल टेक्स्ट एम्बेडिंग (पिछड़ा संगतता)
|
||||
खाली बैच हैंडलिंग
|
||||
अधिकतम बैच आकार का प्रवर्तन
|
||||
आंशिक बैच विफलताओं के लिए त्रुटि हैंडलिंग
|
||||
|
||||
### एकीकरण परीक्षण
|
||||
पल्सर के माध्यम से एंड-टू-एंड बैच एम्बेडिंग
|
||||
ग्राफ एम्बेडिंग सेवा बैच प्रसंस्करण
|
||||
रो एम्बेडिंग सेवा बैच प्रसंस्करण
|
||||
एपीआई गेटवे बैच एंडपॉइंट
|
||||
|
||||
### प्रदर्शन परीक्षण
|
||||
सिंगल बनाम बैच थ्रूपुट का बेंचमार्क
|
||||
विभिन्न बैच आकारों के तहत मेमोरी उपयोग
|
||||
विलंबता वितरण विश्लेषण
|
||||
|
||||
## माइग्रेशन योजना
|
||||
|
||||
यह एक ब्रेकिंग चेंज रिलीज़ है। सभी चरण एक साथ लागू किए गए हैं।
|
||||
|
||||
### चरण 1: स्कीमा परिवर्तन
|
||||
EmbeddingsRequest में `text: str` को `texts: list[str]` से बदलें
|
||||
EmbeddingsResponse में `vectors` प्रकार को `list[list[list[float]]]` में बदलें
|
||||
|
||||
### चरण 2: प्रोसेसर अपडेट
|
||||
FastEmbed और Ollama प्रोसेसर में `on_embeddings` हस्ताक्षर को अपडेट करें
|
||||
सिंगल मॉडल कॉल में पूरा बैच संसाधित करें
|
||||
|
||||
### चरण 3: क्लाइंट अपडेट
|
||||
`EmbeddingsClient.embed()` को `texts: list[str]` स्वीकार करने के लिए अपडेट करें
|
||||
|
||||
### चरण 4: कॉलर अपडेट
|
||||
graph_embeddings को बैच एंटिटी संदर्भों के लिए अपडेट करें
|
||||
row_embeddings को बैच इंडेक्स टेक्स्ट के लिए अपडेट करें
|
||||
document_embeddings को नए स्कीमा का उपयोग करने के लिए अपडेट करें
|
||||
CLI टूल को अपडेट करें
|
||||
|
||||
### चरण 5: एपीआई गेटवे
|
||||
नए स्कीमा के लिए एम्बेडिंग एंडपॉइंट को अपडेट करें
|
||||
|
||||
### चरण 6: पायथन SDK
|
||||
`FlowInstance.embeddings()` हस्ताक्षर को अपडेट करें
|
||||
`SocketFlowInstance.embeddings()` हस्ताक्षर को अपडेट करें
|
||||
|
||||
## खुले प्रश्न
|
||||
|
||||
**बड़े बैचों का स्ट्रीमिंग**: क्या हमें बहुत बड़े बैचों (>100 टेक्स्ट) के लिए स्ट्रीमिंग परिणामों का समर्थन करना चाहिए?
|
||||
**प्रदाता-विशिष्ट सीमाएँ**: हमें विभिन्न अधिकतम बैच आकारों वाले प्रदाताओं को कैसे संभालना चाहिए?
|
||||
**आंशिक विफलता हैंडलिंग**: यदि बैच में एक टेक्स्ट विफल हो जाता है, तो क्या हमें पूरे बैच को विफल करना चाहिए या आंशिक परिणाम लौटाने चाहिए?
|
||||
**डॉक्यूमेंट एम्बेडिंग बैचिंग**: क्या हमें कई चंक संदेशों में बैच करना चाहिए या प्रति-संदेश प्रसंस्करण बनाए रखना चाहिए?
|
||||
|
||||
## संदर्भ
|
||||
|
||||
[FastEmbed Documentation](https://github.com/qdrant/fastembed)
|
||||
[Ollama Embeddings API](https://github.com/ollama/ollama)
|
||||
[EmbeddingsService Implementation](trustgraph-base/trustgraph/base/embeddings_service.py)
|
||||
[GraphRAG Performance Optimization](graphrag-performance-optimization.md)
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Embeddings Batch Processing Technical Specification"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Embeddings Batch Processing Technical Specification
|
||||
|
||||
## Overview
|
||||
|
|
|
|||
675
docs/tech-specs/embeddings-batch-processing.pt.md
Normal file
675
docs/tech-specs/embeddings-batch-processing.pt.md
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificação Técnica de Processamento em Lote de Embeddings"
|
||||
parent: "Portuguese (Beta)"
|
||||
---
|
||||
|
||||
# Especificação Técnica de Processamento em Lote de Embeddings
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Esta especificação descreve otimizações para o serviço de embeddings para suportar o processamento em lote de vários textos em um único pedido. A implementação atual processa um texto por vez, perdendo os benefícios de desempenho significativos que os modelos de embedding oferecem ao processar lotes.
|
||||
|
||||
1. **Ineficiência no Processamento de Texto Único**: A implementação atual envolve textos únicos em uma lista, subutilizando as capacidades de lote do FastEmbed.
|
||||
2. **Sobrecarga de Pedido por Texto**: Cada texto requer uma viagem de ida e volta separada do Pulsar.
|
||||
3. **Ineficiência na Inferência do Modelo**: Os modelos de embedding têm uma sobrecarga fixa por lote; lotes pequenos desperdiçam recursos de GPU/CPU.
|
||||
4. **Processamento Serial nos Clientes**: Serviços importantes fazem loop sobre itens e chamam embeddings um de cada vez.
|
||||
|
||||
## Objetivos
|
||||
|
||||
**Suporte para API de Lote**: Permitir o processamento de vários textos em um único pedido.
|
||||
**Compatibilidade com Versões Anteriores**: Manter o suporte para pedidos de texto único.
|
||||
**Melhora Significativa no Desempenho**: Almejar uma melhora de desempenho de 5 a 10 vezes para operações em lote.
|
||||
**Latência Reduzida por Texto**: Diminuir a latência amortizada ao incorporar vários textos.
|
||||
**Eficiência de Memória**: Processar lotes sem consumo excessivo de memória.
|
||||
**Independente do Provedor**: Suportar o processamento em lote em FastEmbed, Ollama e outros provedores.
|
||||
**Migração do Cliente**: Atualizar todos os clientes de embedding para usar a API de lote sempre que for benéfico.
|
||||
|
||||
## Contexto
|
||||
|
||||
### Implementação Atual - Serviço de Embeddings
|
||||
|
||||
A implementação de embeddings em `trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` apresenta uma ineficiência de desempenho significativa:
|
||||
|
||||
```python
|
||||
# fastembed/processor.py line 56
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
vecs = self.embeddings.embed([text]) # Single text wrapped in list
|
||||
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**Problemas:**
|
||||
|
||||
1. **Tamanho do Lote 1**: O método `embed()` do FastEmbed é otimizado para processamento em lote, mas sempre o chamamos com `[text]` - um lote de tamanho 1.
|
||||
|
||||
2. **Sobrecarga por Requisição**: Cada solicitação de incorporação incorre em:
|
||||
Serialização/desserialização de mensagens Pulsar
|
||||
Latência de ida e volta da rede
|
||||
Sobrecarga de inicialização da inferência do modelo
|
||||
Sobrecarga de agendamento assíncrono do Python
|
||||
|
||||
3. **Limitação do Esquema**: O esquema `EmbeddingsRequest` suporta apenas um único texto:
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
text: str = "" # Single text only
|
||||
```
|
||||
|
||||
### Clientes Atuais - Processamento Serial
|
||||
|
||||
#### 1. Gateway de API
|
||||
|
||||
**Arquivo:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
O gateway aceita solicitações de incorporação de texto único via HTTP/WebSocket e as encaminha para o serviço de incorporação. Atualmente, não existe um endpoint para processamento em lote.
|
||||
|
||||
```python
|
||||
class EmbeddingsRequestor(ServiceRequestor):
|
||||
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
||||
request_schema=EmbeddingsRequest, # Single text only
|
||||
response_schema=EmbeddingsResponse,
|
||||
```
|
||||
|
||||
**Impacto:** Clientes externos (aplicativos web, scripts) devem fazer N requisições HTTP para incorporar N textos.
|
||||
|
||||
#### 2. Serviço de Incorporação de Documentos
|
||||
|
||||
**Arquivo:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
Processa blocos de documentos um de cada vez:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
v = msg.value()
|
||||
|
||||
# Single chunk per request
|
||||
resp = await flow("embeddings-request").request(
|
||||
EmbeddingsRequest(text=v.chunk)
|
||||
)
|
||||
vectors = resp.vectors
|
||||
```
|
||||
|
||||
**Impacto:** Cada trecho de documento requer uma chamada de embedding separada. Um documento com 100 trechos = 100 requisições de embedding.
|
||||
|
||||
#### 3. Serviço de Embeddings de Grafos
|
||||
|
||||
**Arquivo:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
|
||||
Percorre as entidades e incorpora cada uma sequencialmente:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for entity in v.entities:
|
||||
# Serial embedding - one entity at a time
|
||||
vectors = await flow("embeddings-request").embed(
|
||||
text=entity.context
|
||||
)
|
||||
entities.append(EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors,
|
||||
chunk_id=entity.chunk_id,
|
||||
))
|
||||
```
|
||||
|
||||
**Impacto:** Uma mensagem com 50 entidades = 50 solicitações de incorporação serial. Isso é um grande gargalo durante a construção do grafo de conhecimento.
|
||||
|
||||
#### 4. Serviço de Incorporação de Linhas
|
||||
|
||||
**Arquivo:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
|
||||
Percorre textos únicos e incorpora cada um serialmente:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
# Serial embedding - one text at a time
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
|
||||
embeddings_list.append(RowIndexEmbedding(
|
||||
index_name=index_name,
|
||||
index_value=index_value,
|
||||
text=text,
|
||||
vectors=vectors
|
||||
))
|
||||
```
|
||||
|
||||
**Impacto:** Processar uma tabela com 100 valores indexados únicos = 100 solicitações de incorporação seriais.
|
||||
|
||||
#### 5. EmbeddingsClient (Cliente Base)
|
||||
|
||||
**Arquivo:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
O cliente usado por todos os processadores de fluxo suporta apenas a incorporação de texto único:
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(self, text, timeout=30):
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(text=text), # Single text
|
||||
timeout=timeout
|
||||
)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
**Impacto:** Todos os clientes que utilizam este componente estão limitados a operações de texto único.
|
||||
|
||||
#### 6. Ferramentas de Linha de Comando
|
||||
|
||||
**Arquivo:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
A ferramenta de linha de comando aceita um único argumento de texto:
|
||||
|
||||
```python
|
||||
def query(url, flow_id, text, token=None):
|
||||
result = flow.embeddings(text=text) # Single text
|
||||
vectors = result.get("vectors", [])
|
||||
```
|
||||
|
||||
**Impacto:** Os usuários não podem realizar incorporações em lote a partir da linha de comando. O processamento de um arquivo de textos requer N invocações.
|
||||
|
||||
#### 7. SDK Python
|
||||
|
||||
O SDK Python fornece duas classes de cliente para interagir com os serviços da TrustGraph. Ambas suportam apenas a incorporação de um único texto.
|
||||
|
||||
**Arquivo:** `trustgraph-base/trustgraph/api/flow.py`
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, text):
|
||||
"""Get embeddings for a single text"""
|
||||
input = {"text": text}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**Arquivo:** `trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, text: str, **kwargs: Any) -> Dict[str, Any]:
|
||||
"""Get embeddings for a single text via WebSocket"""
|
||||
request = {"text": text}
|
||||
return self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
```
|
||||
|
||||
**Impacto:** Desenvolvedores Python que usam o SDK precisam iterar sobre textos e fazer N chamadas de API separadas. Não existe suporte para processamento em lote de embeddings para usuários do SDK.
|
||||
|
||||
### Impacto no Desempenho
|
||||
|
||||
Para ingestão típica de documentos (1000 trechos de texto):
|
||||
**Atual:** 1000 requisições separadas, 1000 chamadas de inferência de modelo
|
||||
**Em lote (batch_size=32):** 32 requisições, 32 chamadas de inferência de modelo (redução de 96,8%)
|
||||
|
||||
Para embedding de grafos (mensagem com 50 entidades):
|
||||
**Atual:** 50 chamadas `await` sequenciais, ~5-10 segundos
|
||||
**Em lote:** 1-2 chamadas em lote, ~0,5-1 segundo (melhora de 5-10x)
|
||||
|
||||
Bibliotecas como FastEmbed e similares alcançam escalabilidade quase linear no throughput com o tamanho do lote, até os limites do hardware (tipicamente 32-128 textos por lote).
|
||||
|
||||
## Design Técnico
|
||||
|
||||
### Arquitetura
|
||||
|
||||
A otimização de processamento em lote de embeddings requer alterações nos seguintes componentes:
|
||||
|
||||
#### 1. **Aprimoramento do Esquema**
|
||||
Estender `EmbeddingsRequest` para suportar múltiplos textos
|
||||
Estender `EmbeddingsResponse` para retornar múltiplos conjuntos de vetores
|
||||
Manter a compatibilidade retroativa com requisições de texto único
|
||||
|
||||
Módulo: `trustgraph-base/trustgraph/schema/services/llm.py`
|
||||
|
||||
#### 2. **Aprimoramento do Serviço Base**
|
||||
Atualizar `EmbeddingsService` para lidar com requisições em lote
|
||||
Adicionar configuração do tamanho do lote
|
||||
Implementar tratamento de requisições com suporte a lote
|
||||
|
||||
Módulo: `trustgraph-base/trustgraph/base/embeddings_service.py`
|
||||
|
||||
#### 3. **Atualizações do Processador do Provedor**
|
||||
Atualizar o processador FastEmbed para passar o lote completo para `embed()`
|
||||
Atualizar o processador Ollama para lidar com lotes (se suportado)
|
||||
Adicionar processamento sequencial como fallback para provedores sem suporte a lote
|
||||
|
||||
Módulos:
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
||||
|
||||
#### 4. **Aprimoramento do Cliente**
|
||||
Adicionar método de embedding em lote para `EmbeddingsClient`
|
||||
Suportar APIs de texto único e em lote
|
||||
Adicionar agrupamento automático para grandes entradas
|
||||
|
||||
Módulo: `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
#### 5. **Atualizações do Chamador - Processadores de Fluxo**
|
||||
Atualizar `graph_embeddings` para agrupar contextos de entidades
|
||||
Atualizar `row_embeddings` para agrupar textos de índice
|
||||
Atualizar `document_embeddings` se o agrupamento de mensagens for viável
|
||||
|
||||
Módulos:
|
||||
`trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
#### 6. **Aprimoramento do Gateway de API**
|
||||
Adicionar endpoint de embedding em lote
|
||||
Suportar array de textos no corpo da requisição
|
||||
|
||||
Módulo: `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
#### 7. **Aprimoramento da Ferramenta de Linha de Comando (CLI)**
|
||||
Adicionar suporte para múltiplos textos ou entrada de arquivo
|
||||
Adicionar parâmetro de tamanho do lote
|
||||
|
||||
Módulo: `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
#### 8. **Aprimoramento do SDK Python**
|
||||
Adicionar método `embeddings_batch()` para `FlowInstance`
|
||||
Adicionar método `embeddings_batch()` para `SocketFlowInstance`
|
||||
Suportar APIs de texto único e em lote para usuários do SDK
|
||||
|
||||
Módulos:
|
||||
`trustgraph-base/trustgraph/api/flow.py`
|
||||
`trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
### Modelos de Dados
|
||||
|
||||
#### EmbeddingsRequest
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Uso:
|
||||
Texto único: `EmbeddingsRequest(texts=["hello world"])`
|
||||
Lote: `EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
||||
|
||||
#### EmbeddingsResponse
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Estrutura da resposta:
|
||||
`vectors[i]` contém o conjunto de vetores para `texts[i]`
|
||||
Cada conjunto de vetores é `list[list[float]]` (os modelos podem retornar vários vetores por texto)
|
||||
Exemplo: 3 textos → `vectors` tem 3 entradas, cada uma contendo os embeddings desse texto
|
||||
|
||||
### APIs
|
||||
|
||||
#### EmbeddingsClient
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(
|
||||
self,
|
||||
texts: list[str],
|
||||
timeout: float = 300,
|
||||
) -> list[list[list[float]]]:
|
||||
"""
|
||||
Embed one or more texts in a single request.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
timeout: Timeout for the operation
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(texts=texts),
|
||||
timeout=timeout
|
||||
)
|
||||
if resp.error:
|
||||
raise RuntimeError(resp.error.message)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
#### Endpoint de Incorporação do Gateway de API
|
||||
|
||||
Endpoint atualizado que suporta incorporação única ou em lote:
|
||||
|
||||
```
|
||||
POST /api/v1/embeddings
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"texts": ["text1", "text2", "text3"],
|
||||
"flow_id": "default"
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"vectors": [
|
||||
[[0.1, 0.2, ...]],
|
||||
[[0.3, 0.4, ...]],
|
||||
[[0.5, 0.6, ...]]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Detalhes de Implementação
|
||||
|
||||
#### Fase 1: Alterações no Esquema
|
||||
|
||||
**EmbeddingsRequest:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**EmbeddingsResponse:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**Atualizado EmbeddingsService.on_request:**
|
||||
```python
|
||||
async def on_request(self, msg, consumer, flow):
|
||||
request = msg.value()
|
||||
id = msg.properties()["id"]
|
||||
model = flow("model")
|
||||
|
||||
vectors = await self.on_embeddings(request.texts, model=model)
|
||||
response = EmbeddingsResponse(error=None, vectors=vectors)
|
||||
|
||||
await flow("response").send(response, properties={"id": id})
|
||||
```
|
||||
|
||||
#### Fase 2: Atualização do Processador FastEmbed
|
||||
|
||||
**Atual (Ineficiente):**
|
||||
```python
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
vecs = self.embeddings.embed([text]) # Batch of 1
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**Atualizado:**
|
||||
```python
|
||||
async def on_embeddings(self, texts: list[str], model=None):
|
||||
"""Embed texts - processes all texts in single model call"""
|
||||
if not texts:
|
||||
return []
|
||||
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
# FastEmbed handles the full batch efficiently
|
||||
all_vecs = list(self.embeddings.embed(texts))
|
||||
|
||||
# Return list of vector sets, one per input text
|
||||
return [[v.tolist()] for v in all_vecs]
|
||||
```
|
||||
|
||||
#### Fase 3: Atualização do Serviço de Incorporação de Grafos
|
||||
|
||||
**Atual (Serial):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
entities = []
|
||||
for entity in v.entities:
|
||||
vectors = await flow("embeddings-request").embed(text=entity.context)
|
||||
entities.append(EntityEmbeddings(...))
|
||||
```
|
||||
|
||||
**Atualizado (Lote):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
# Collect all contexts
|
||||
contexts = [entity.context for entity in v.entities]
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=contexts)
|
||||
|
||||
# Pair results with entities
|
||||
entities = [
|
||||
EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors[0], # First vector from the set
|
||||
chunk_id=entity.chunk_id,
|
||||
)
|
||||
for entity, vectors in zip(v.entities, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### Fase 4: Atualização do Serviço de Incorporação de Dados
|
||||
|
||||
**Atual (Serial):**
|
||||
```python
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
embeddings_list.append(RowIndexEmbedding(...))
|
||||
```
|
||||
|
||||
**Atualizado (Lote):**
|
||||
```python
|
||||
# Collect texts and metadata
|
||||
texts = list(texts_to_embed.keys())
|
||||
metadata = list(texts_to_embed.values())
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=texts)
|
||||
|
||||
# Pair results
|
||||
embeddings_list = [
|
||||
RowIndexEmbedding(
|
||||
index_name=meta[0],
|
||||
index_value=meta[1],
|
||||
text=text,
|
||||
vectors=vectors[0] # First vector from the set
|
||||
)
|
||||
for text, meta, vectors in zip(texts, metadata, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### Fase 5: Melhoria da Ferramenta de Linha de Comando (CLI)
|
||||
|
||||
**CLI Atualizado:**
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(...)
|
||||
|
||||
parser.add_argument(
|
||||
'text',
|
||||
nargs='*', # Zero or more texts
|
||||
help='Text(s) to convert to embedding vectors',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--file',
|
||||
help='File containing texts (one per line)',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--batch-size',
|
||||
type=int,
|
||||
default=32,
|
||||
help='Batch size for processing (default: 32)',
|
||||
)
|
||||
```
|
||||
|
||||
Uso:
|
||||
```bash
|
||||
# Single text (existing)
|
||||
tg-invoke-embeddings "hello world"
|
||||
|
||||
# Multiple texts
|
||||
tg-invoke-embeddings "text one" "text two" "text three"
|
||||
|
||||
# From file
|
||||
tg-invoke-embeddings -f texts.txt --batch-size 64
|
||||
```
|
||||
|
||||
#### Fase 6: Melhoria do SDK Python
|
||||
|
||||
**FlowInstance (cliente HTTP):**
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, texts: list[str]) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
input = {"texts": texts}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**SocketFlowInstance (cliente WebSocket):**
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts via WebSocket.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
request = {"texts": texts}
|
||||
response = self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
return response["vectors"]
|
||||
```
|
||||
|
||||
**Exemplos de uso do SDK:**
|
||||
|
||||
```python
|
||||
# Single text
|
||||
vectors = flow.embeddings(["hello world"])
|
||||
print(f"Dimensions: {len(vectors[0][0])}")
|
||||
|
||||
# Batch embedding
|
||||
texts = ["text one", "text two", "text three"]
|
||||
all_vectors = flow.embeddings(texts)
|
||||
|
||||
# Process results
|
||||
for text, vecs in zip(texts, all_vectors):
|
||||
print(f"{text}: {len(vecs[0])} dimensions")
|
||||
```
|
||||
|
||||
## Considerações de Segurança
|
||||
|
||||
**Limites de Tamanho da Requisição**: Impor o tamanho máximo do lote para evitar o esgotamento de recursos.
|
||||
**Tratamento de Tempo Limite (Timeout)**: Ajustar os tempos limite de acordo com o tamanho do lote.
|
||||
**Limites de Memória**: Monitorar o uso de memória para grandes lotes.
|
||||
**Validação de Entrada**: Validar todos os textos no lote antes do processamento.
|
||||
|
||||
## Considerações de Desempenho
|
||||
|
||||
### Melhorias Esperadas
|
||||
|
||||
**Taxa de Transferência (Throughput):**
|
||||
Texto único: ~10-50 textos/segundo (dependendo do modelo)
|
||||
Lote (tamanho 32): ~200-500 textos/segundo (melhora de 5 a 10 vezes)
|
||||
|
||||
**Latência por Texto:**
|
||||
Texto único: 50-200ms por texto
|
||||
Lote (tamanho 32): 5-20ms por texto (média)
|
||||
|
||||
**Melhorias Específicas do Serviço:**
|
||||
|
||||
| Serviço | Atual | Em Lote | Melhoria |
|
||||
|---------|---------|---------|-------------|
|
||||
| Incorporações de Grafos (50 entidades) | 5-10s | 0,5-1s | 5-10x |
|
||||
| Incorporações de Linhas (100 textos) | 10-20s | 1-2s | 5-10x |
|
||||
| Ingestão de Documentos (1000 fragmentos) | 100-200s | 10-30s | 5-10x |
|
||||
|
||||
### Parâmetros de Configuração
|
||||
|
||||
```python
|
||||
# Recommended defaults
|
||||
DEFAULT_BATCH_SIZE = 32
|
||||
MAX_BATCH_SIZE = 128
|
||||
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
||||
```
|
||||
|
||||
## Estratégia de Testes
|
||||
|
||||
### Testes Unitários
|
||||
Incorporação de texto única (compatibilidade com versões anteriores)
|
||||
Tratamento de lotes vazios
|
||||
Imposição do tamanho máximo do lote
|
||||
Tratamento de erros para falhas parciais do lote
|
||||
|
||||
### Testes de Integração
|
||||
Incorporação de lote de ponta a ponta através do Pulsar
|
||||
Processamento de lote do serviço de incorporação de grafos
|
||||
Processamento de lote do serviço de incorporação de linhas
|
||||
Endpoint de lote do gateway de API
|
||||
|
||||
### Testes de Desempenho
|
||||
Comparação de benchmark de taxa de transferência única versus lote
|
||||
Uso de memória sob vários tamanhos de lote
|
||||
Análise da distribuição de latência
|
||||
|
||||
## Plano de Migração
|
||||
|
||||
Esta é uma versão que introduz alterações significativas. Todas as fases são implementadas juntas.
|
||||
|
||||
### Fase 1: Alterações no Esquema
|
||||
Substituir `text: str` por `texts: list[str]` em EmbeddingsRequest
|
||||
Alterar o tipo de `vectors` para `list[list[list[float]]]` em EmbeddingsResponse
|
||||
|
||||
### Fase 2: Atualizações do Processador
|
||||
Atualizar a assinatura de `on_embeddings` nos processadores FastEmbed e Ollama
|
||||
Processar o lote completo em uma única chamada de modelo
|
||||
|
||||
### Fase 3: Atualizações do Cliente
|
||||
Atualizar `EmbeddingsClient.embed()` para aceitar `texts: list[str]`
|
||||
|
||||
### Fase 4: Atualizações do Chamador
|
||||
Atualizar graph_embeddings para incorporar contextos de entidades em lote
|
||||
Atualizar row_embeddings para incorporar textos de índice em lote
|
||||
Atualizar document_embeddings para usar o novo esquema
|
||||
Atualizar a ferramenta de linha de comando (CLI)
|
||||
|
||||
### Fase 5: Gateway de API
|
||||
Atualizar o endpoint de incorporação para o novo esquema
|
||||
|
||||
### Fase 6: SDK Python
|
||||
Atualizar a assinatura de `FlowInstance.embeddings()`
|
||||
Atualizar a assinatura de `SocketFlowInstance.embeddings()`
|
||||
|
||||
## Perguntas Abertas
|
||||
|
||||
**Incorporação de Lotes Grandes em Streaming**: Devemos suportar o streaming de resultados para lotes muito grandes (>100 textos)?
|
||||
**Limites Específicos do Provedor**: Como devemos lidar com provedores com tamanhos máximos de lote diferentes?
|
||||
**Tratamento de Falhas Parciais**: Se um texto em um lote falhar, devemos falhar o lote inteiro ou retornar resultados parciais?
|
||||
**Incorporação em Lote de Documentos**: Devemos incorporar em lote em várias mensagens de Chunk ou manter o processamento por mensagem?
|
||||
|
||||
## Referências
|
||||
|
||||
[Documentação do FastEmbed](https://github.com/qdrant/fastembed)
|
||||
[API de Incorporação do Ollama](https://github.com/ollama/ollama)
|
||||
[Implementação do Serviço de Incorporação](trustgraph-base/trustgraph/base/embeddings_service.py)
|
||||
[Otimização de Desempenho do GraphRAG](graphrag-performance-optimization.md)
|
||||
675
docs/tech-specs/embeddings-batch-processing.ru.md
Normal file
675
docs/tech-specs/embeddings-batch-processing.ru.md
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Техническая спецификация пакетной обработки эмбеддингов"
|
||||
parent: "Russian (Beta)"
|
||||
---
|
||||
|
||||
# Техническая спецификация пакетной обработки эмбеддингов
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Обзор
|
||||
|
||||
Эта спецификация описывает оптимизации для сервиса эмбеддингов, предназначенные для поддержки пакетной обработки нескольких текстов в одном запросе. Текущая реализация обрабатывает один текст за раз, что не позволяет использовать значительные преимущества, которые предоставляют модели эмбеддингов при обработке пакетов.
|
||||
|
||||
1. **Неэффективность обработки одного текста**: Текущая реализация оборачивает отдельные тексты в список, что не позволяет в полной мере использовать возможности пакетной обработки FastEmbed.
|
||||
2. **Накладные расходы на запрос для каждого текста**: Для каждого текста требуется отдельная передача сообщения Pulsar.
|
||||
3. **Неэффективность вывода модели**: Модели эмбеддингов имеют фиксированные накладные расходы на пакет; небольшие пакеты приводят к неэффективному использованию ресурсов GPU/CPU.
|
||||
4. **Последовательная обработка в вызывающих сервисах**: Основные сервисы перебирают элементы и вызывают эмбеддинги по одному.
|
||||
|
||||
## Цели
|
||||
|
||||
**Поддержка пакетного API**: Обеспечить возможность обработки нескольких текстов в одном запросе.
|
||||
**Обратная совместимость**: Сохранить поддержку запросов для обработки одного текста.
|
||||
**Значительное повышение производительности**: Стремиться к увеличению производительности в 5-10 раз для массовых операций.
|
||||
**Снижение задержки на текст**: Уменьшить среднюю задержку при создании эмбеддингов для нескольких текстов.
|
||||
**Эффективность использования памяти**: Обрабатывать пакеты без чрезмерного потребления памяти.
|
||||
**Независимость от провайдера**: Поддерживать пакетную обработку для FastEmbed, Ollama и других провайдеров.
|
||||
**Миграция вызывающих сервисов**: Обновить все сервисы, вызывающие эмбеддинги, для использования пакетного API, где это целесообразно.
|
||||
|
||||
## Контекст
|
||||
|
||||
### Текущая реализация - Сервис эмбеддингов
|
||||
|
||||
Реализация эмбеддингов в `trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` демонстрирует значительную неэффективность:
|
||||
|
||||
```python
|
||||
# fastembed/processor.py line 56
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
vecs = self.embeddings.embed([text]) # Single text wrapped in list
|
||||
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**Проблемы:**
|
||||
|
||||
1. **Размер пакета 1**: Метод `embed()` FastEmbed оптимизирован для пакетной обработки, но мы всегда вызываем его с `[text]` - пакетом размера 1.
|
||||
|
||||
2. **Накладные расходы на каждый запрос**: Каждый запрос на получение эмбеддингов влечет за собой:
|
||||
Сериализацию/десериализацию сообщения Pulsar.
|
||||
Задержку сетевого обмена.
|
||||
Накладные расходы на запуск инференса модели.
|
||||
Накладные расходы на асинхронное планирование Python.
|
||||
|
||||
3. **Ограничение схемы**: Схема `EmbeddingsRequest` поддерживает только один текстовый фрагмент:
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
text: str = "" # Single text only
|
||||
```
|
||||
|
||||
### Текущие вызывающие стороны - последовательная обработка
|
||||
|
||||
#### 1. API-шлюз
|
||||
|
||||
**Файл:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
Шлюз принимает запросы на однострочное создание векторных представлений через HTTP/WebSocket и перенаправляет их в сервис создания векторных представлений. В настоящее время нет пакетного интерфейса.
|
||||
|
||||
```python
|
||||
class EmbeddingsRequestor(ServiceRequestor):
|
||||
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
||||
request_schema=EmbeddingsRequest, # Single text only
|
||||
response_schema=EmbeddingsResponse,
|
||||
```
|
||||
|
||||
**Влияние:** Внешние клиенты (веб-приложения, скрипты) должны выполнять N HTTP-запросов для встраивания N текстов.
|
||||
|
||||
#### 2. Сервис встраивания документов
|
||||
|
||||
**Файл:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
Обрабатывает фрагменты документов по одному.
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
v = msg.value()
|
||||
|
||||
# Single chunk per request
|
||||
resp = await flow("embeddings-request").request(
|
||||
EmbeddingsRequest(text=v.chunk)
|
||||
)
|
||||
vectors = resp.vectors
|
||||
```
|
||||
|
||||
**Влияние:** Каждый фрагмент документа требует отдельного вызова для создания эмбеддинга. Документ, состоящий из 100 фрагментов, = 100 запросов на создание эмбеддингов.
|
||||
|
||||
#### 3. Сервис создания графовых эмбеддингов
|
||||
|
||||
**Файл:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
|
||||
Выполняет итерации по сущностям и создает эмбеддинг для каждой из них последовательно:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for entity in v.entities:
|
||||
# Serial embedding - one entity at a time
|
||||
vectors = await flow("embeddings-request").embed(
|
||||
text=entity.context
|
||||
)
|
||||
entities.append(EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors,
|
||||
chunk_id=entity.chunk_id,
|
||||
))
|
||||
```
|
||||
|
||||
**Влияние:** Сообщение, содержащее 50 сущностей, приводит к 50 последовательным запросам на создание векторных представлений. Это серьезное препятствие при построении графа знаний.
|
||||
|
||||
#### 4. Сервис создания векторных представлений строк
|
||||
|
||||
**Файл:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
|
||||
Выполняет итерации по уникальным текстам и создает векторное представление для каждого из них последовательно:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
# Serial embedding - one text at a time
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
|
||||
embeddings_list.append(RowIndexEmbedding(
|
||||
index_name=index_name,
|
||||
index_value=index_value,
|
||||
text=text,
|
||||
vectors=vectors
|
||||
))
|
||||
```
|
||||
|
||||
**Влияние:** Обработка таблицы с 100 уникальными индексированными значениями = 100 последовательных запросов на создание векторных представлений.
|
||||
|
||||
#### 5. EmbeddingsClient (Базовый клиент)
|
||||
|
||||
**Файл:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
Клиент, используемый всеми процессорами потоков, поддерживает только создание векторных представлений для одного текстового фрагмента:
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(self, text, timeout=30):
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(text=text), # Single text
|
||||
timeout=timeout
|
||||
)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
**Влияние:** Все клиенты, использующие этот компонент, ограничены операциями с одним текстовым фрагментом.
|
||||
|
||||
#### 6. Инструменты командной строки
|
||||
|
||||
**Файл:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
Инструмент командной строки принимает один текстовый аргумент:
|
||||
|
||||
```python
|
||||
def query(url, flow_id, text, token=None):
|
||||
result = flow.embeddings(text=text) # Single text
|
||||
vectors = result.get("vectors", [])
|
||||
```
|
||||
|
||||
**Влияние:** Пользователи не могут выполнять пакетную вставку из командной строки. Обработка файла текстов требует N вызовов.
|
||||
|
||||
#### 7. Python SDK
|
||||
|
||||
Python SDK предоставляет два клиентских класса для взаимодействия со службами TrustGraph. Оба поддерживают только вставку одного текста.
|
||||
|
||||
**Файл:** `trustgraph-base/trustgraph/api/flow.py`
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, text):
|
||||
"""Get embeddings for a single text"""
|
||||
input = {"text": text}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**Файл:** `trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, text: str, **kwargs: Any) -> Dict[str, Any]:
|
||||
"""Get embeddings for a single text via WebSocket"""
|
||||
request = {"text": text}
|
||||
return self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
```
|
||||
|
||||
**Влияние:** Разработчикам Python, использующим SDK, необходимо перебирать тексты и выполнять N отдельных API-запросов. Поддержка пакетной обработки векторов для пользователей SDK отсутствует.
|
||||
|
||||
### Влияние на производительность
|
||||
|
||||
Для типичного извлечения данных (1000 текстовых фрагментов):
|
||||
**Текущая ситуация:** 1000 отдельных запросов, 1000 вызовов модели для получения векторов.
|
||||
**Пакетная обработка (batch_size=32):** 32 запроса, 32 вызова модели для получения векторов (снижение на 96,8%).
|
||||
|
||||
Для получения векторов графа (сообщение с 50 сущностями):
|
||||
**Текущая ситуация:** 50 последовательных вызовов `await`, ~5-10 секунд.
|
||||
**Пакетная обработка:** 1-2 пакетных вызова, ~0,5-1 секунда (улучшение в 5-10 раз).
|
||||
|
||||
Библиотеки FastEmbed и аналогичные достигают почти линейного увеличения производительности при увеличении размера пакета до пределов аппаратного обеспечения (обычно 32-128 текстов на пакет).
|
||||
|
||||
## Техническое проектирование
|
||||
|
||||
### Архитектура
|
||||
|
||||
Оптимизация пакетной обработки векторов требует изменений в следующих компонентах:
|
||||
|
||||
#### 1. **Улучшение схемы данных**
|
||||
Расширить `EmbeddingsRequest` для поддержки нескольких текстов.
|
||||
Расширить `EmbeddingsResponse` для возврата нескольких наборов векторов.
|
||||
Сохранить обратную совместимость с запросами для одного текста.
|
||||
|
||||
Модуль: `trustgraph-base/trustgraph/schema/services/llm.py`
|
||||
|
||||
#### 2. **Улучшение базового сервиса**
|
||||
Обновить `EmbeddingsService` для обработки пакетных запросов.
|
||||
Добавить конфигурацию размера пакета.
|
||||
Реализовать обработку запросов с учетом пакетной обработки.
|
||||
|
||||
Модуль: `trustgraph-base/trustgraph/base/embeddings_service.py`
|
||||
|
||||
#### 3. **Обновления для процессоров провайдеров**
|
||||
Обновить процессор FastEmbed для передачи полного пакета в `embed()`.
|
||||
Обновить процессор Ollama для обработки пакетов (если поддерживается).
|
||||
Добавить последовательную обработку в качестве запасного варианта для провайдеров, не поддерживающих пакетную обработку.
|
||||
|
||||
Модули:
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
||||
|
||||
#### 4. **Улучшение клиентской библиотеки**
|
||||
Добавить метод пакетной обработки векторов в `EmbeddingsClient`.
|
||||
Поддерживать как одиночные, так и пакетные API.
|
||||
Добавить автоматическую пакетную обработку для больших входных данных.
|
||||
|
||||
Модуль: `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
#### 5. **Обновления для вызывающего кода - процессоров потоков**
|
||||
Обновить `graph_embeddings` для пакетной обработки контекстов сущностей.
|
||||
Обновить `row_embeddings` для пакетной обработки текстов для индексации.
|
||||
Обновить `document_embeddings`, если пакетная обработка сообщений возможна.
|
||||
|
||||
Модули:
|
||||
`trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
#### 6. **Улучшение API-шлюза**
|
||||
Добавить конечную точку для пакетной обработки векторов.
|
||||
Поддерживать массив текстов в теле запроса.
|
||||
|
||||
Модуль: `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
#### 7. **Улучшение инструмента командной строки (CLI)**
|
||||
Добавить поддержку нескольких текстов или ввода из файла.
|
||||
Добавить параметр размера пакета.
|
||||
|
||||
Модуль: `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
#### 8. **Улучшение Python SDK**
|
||||
Добавить метод `embeddings_batch()` в `FlowInstance`.
|
||||
Добавить метод `embeddings_batch()` в `SocketFlowInstance`.
|
||||
Поддерживать как одиночные, так и пакетные API для пользователей SDK.
|
||||
|
||||
Модули:
|
||||
`trustgraph-base/trustgraph/api/flow.py`
|
||||
`trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
### Модели данных
|
||||
|
||||
#### EmbeddingsRequest
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Использование:
|
||||
Одиночный текст: `EmbeddingsRequest(texts=["hello world"])`
|
||||
Пакетный режим: `EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
||||
|
||||
#### EmbeddingsResponse
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Структура ответа:
|
||||
`vectors[i]` содержит набор векторов для `texts[i]`
|
||||
Каждый набор векторов имеет размер `list[list[float]]` (модели могут возвращать несколько векторов для одного текста)
|
||||
Пример: 3 текста → `vectors` имеет 3 записи, каждая из которых содержит векторные представления этого текста
|
||||
|
||||
### API
|
||||
|
||||
#### EmbeddingsClient
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(
|
||||
self,
|
||||
texts: list[str],
|
||||
timeout: float = 300,
|
||||
) -> list[list[list[float]]]:
|
||||
"""
|
||||
Embed one or more texts in a single request.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
timeout: Timeout for the operation
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(texts=texts),
|
||||
timeout=timeout
|
||||
)
|
||||
if resp.error:
|
||||
raise RuntimeError(resp.error.message)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
#### Конечная точка API Gateway для встраиваемых объектов
|
||||
|
||||
Обновленная конечная точка, поддерживающая однократную или пакетную генерацию встраиваемых объектов:
|
||||
|
||||
```
|
||||
POST /api/v1/embeddings
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"texts": ["text1", "text2", "text3"],
|
||||
"flow_id": "default"
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"vectors": [
|
||||
[[0.1, 0.2, ...]],
|
||||
[[0.3, 0.4, ...]],
|
||||
[[0.5, 0.6, ...]]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Детали реализации
|
||||
|
||||
#### Этап 1: Изменения схемы
|
||||
|
||||
**EmbeddingsRequest:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**Ответ Embeddings:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**Обновлен класс EmbeddingsService.on_request:**
|
||||
```python
|
||||
async def on_request(self, msg, consumer, flow):
|
||||
request = msg.value()
|
||||
id = msg.properties()["id"]
|
||||
model = flow("model")
|
||||
|
||||
vectors = await self.on_embeddings(request.texts, model=model)
|
||||
response = EmbeddingsResponse(error=None, vectors=vectors)
|
||||
|
||||
await flow("response").send(response, properties={"id": id})
|
||||
```
|
||||
|
||||
#### Фаза 2: Обновление процессора FastEmbed
|
||||
|
||||
**Текущая (неэффективная):**
|
||||
```python
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
vecs = self.embeddings.embed([text]) # Batch of 1
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**Обновлено:**
|
||||
```python
|
||||
async def on_embeddings(self, texts: list[str], model=None):
|
||||
"""Embed texts - processes all texts in single model call"""
|
||||
if not texts:
|
||||
return []
|
||||
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
# FastEmbed handles the full batch efficiently
|
||||
all_vecs = list(self.embeddings.embed(texts))
|
||||
|
||||
# Return list of vector sets, one per input text
|
||||
return [[v.tolist()] for v in all_vecs]
|
||||
```
|
||||
|
||||
#### Фаза 3: Обновление сервиса графовых вложений
|
||||
|
||||
**Текущая (последовательная):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
entities = []
|
||||
for entity in v.entities:
|
||||
vectors = await flow("embeddings-request").embed(text=entity.context)
|
||||
entities.append(EntityEmbeddings(...))
|
||||
```
|
||||
|
||||
**Обновлено (пакетно):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
# Collect all contexts
|
||||
contexts = [entity.context for entity in v.entities]
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=contexts)
|
||||
|
||||
# Pair results with entities
|
||||
entities = [
|
||||
EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors[0], # First vector from the set
|
||||
chunk_id=entity.chunk_id,
|
||||
)
|
||||
for entity, vectors in zip(v.entities, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### Фаза 4: Обновление сервиса встраивания данных.
|
||||
|
||||
**Текущая (последовательная):**
|
||||
```python
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
embeddings_list.append(RowIndexEmbedding(...))
|
||||
```
|
||||
|
||||
**Обновлено (пакетно):**
|
||||
```python
|
||||
# Collect texts and metadata
|
||||
texts = list(texts_to_embed.keys())
|
||||
metadata = list(texts_to_embed.values())
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=texts)
|
||||
|
||||
# Pair results
|
||||
embeddings_list = [
|
||||
RowIndexEmbedding(
|
||||
index_name=meta[0],
|
||||
index_value=meta[1],
|
||||
text=text,
|
||||
vectors=vectors[0] # First vector from the set
|
||||
)
|
||||
for text, meta, vectors in zip(texts, metadata, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### Фаза 5: Улучшение инструмента командной строки (CLI).
|
||||
|
||||
**Обновленный CLI:**
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(...)
|
||||
|
||||
parser.add_argument(
|
||||
'text',
|
||||
nargs='*', # Zero or more texts
|
||||
help='Text(s) to convert to embedding vectors',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--file',
|
||||
help='File containing texts (one per line)',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--batch-size',
|
||||
type=int,
|
||||
default=32,
|
||||
help='Batch size for processing (default: 32)',
|
||||
)
|
||||
```
|
||||
|
||||
Использование:
|
||||
```bash
|
||||
# Single text (existing)
|
||||
tg-invoke-embeddings "hello world"
|
||||
|
||||
# Multiple texts
|
||||
tg-invoke-embeddings "text one" "text two" "text three"
|
||||
|
||||
# From file
|
||||
tg-invoke-embeddings -f texts.txt --batch-size 64
|
||||
```
|
||||
|
||||
#### Фаза 6: Улучшение SDK для Python
|
||||
|
||||
**FlowInstance (HTTP-клиент):**
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, texts: list[str]) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
input = {"texts": texts}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**SocketFlowInstance (клиент WebSocket):**
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts via WebSocket.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
request = {"texts": texts}
|
||||
response = self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
return response["vectors"]
|
||||
```
|
||||
|
||||
**Примеры использования SDK:**
|
||||
|
||||
```python
|
||||
# Single text
|
||||
vectors = flow.embeddings(["hello world"])
|
||||
print(f"Dimensions: {len(vectors[0][0])}")
|
||||
|
||||
# Batch embedding
|
||||
texts = ["text one", "text two", "text three"]
|
||||
all_vectors = flow.embeddings(texts)
|
||||
|
||||
# Process results
|
||||
for text, vecs in zip(texts, all_vectors):
|
||||
print(f"{text}: {len(vecs[0])} dimensions")
|
||||
```
|
||||
|
||||
## Соображения безопасности
|
||||
|
||||
**Ограничения на размер запроса**: Установите максимальный размер пакета для предотвращения исчерпания ресурсов.
|
||||
**Обработка таймаутов**: Адаптируйте таймауты в соответствии с размером пакета.
|
||||
**Ограничения памяти**: Отслеживайте использование памяти для больших пакетов.
|
||||
**Проверка входных данных**: Проверяйте все тексты в пакете перед обработкой.
|
||||
|
||||
## Соображения производительности
|
||||
|
||||
### Ожидаемые улучшения
|
||||
|
||||
**Производительность:**
|
||||
Для одного текста: ~10-50 текстов/секунду (в зависимости от модели).
|
||||
Для пакета (размер 32): ~200-500 текстов/секунду (улучшение в 5-10 раз).
|
||||
|
||||
**Задержка на текст:**
|
||||
Для одного текста: 50-200 мс на текст.
|
||||
Для пакета (размер 32): 5-20 мс на текст (в среднем).
|
||||
|
||||
**Улучшения для конкретных сервисов:**
|
||||
|
||||
| Сервис | Текущее значение | Пакетный режим | Улучшение |
|
||||
|---------|---------|---------|-------------|
|
||||
| Векторные представления графов (50 сущностей) | 5-10 секунд | 0.5-1 секунда | 5-10x |
|
||||
| Векторные представления строк (100 текстов) | 10-20 секунд | 1-2 секунды | 5-10x |
|
||||
| Импорт документов (1000 фрагментов) | 100-200 секунд | 10-30 секунд | 5-10x |
|
||||
|
||||
### Параметры конфигурации
|
||||
|
||||
```python
|
||||
# Recommended defaults
|
||||
DEFAULT_BATCH_SIZE = 32
|
||||
MAX_BATCH_SIZE = 128
|
||||
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
||||
```
|
||||
|
||||
## Стратегия тестирования
|
||||
|
||||
### Модульное тестирование
|
||||
Обработка однострочных вложений (обратная совместимость)
|
||||
Обработка пустых пакетов
|
||||
Применение максимального размера пакета
|
||||
Обработка ошибок при частичных сбоях пакета
|
||||
|
||||
### Интеграционное тестирование
|
||||
Полная обработка пакетов через Pulsar
|
||||
Обработка пакетов сервисом графовых вложений
|
||||
Обработка пакетов сервисом строковых вложений
|
||||
API-шлюз для пакетных операций
|
||||
|
||||
### Тестирование производительности
|
||||
Сравнение производительности при обработке отдельных элементов и пакетов
|
||||
Использование памяти при различных размерах пакетов
|
||||
Анализ распределения задержек
|
||||
|
||||
## План миграции
|
||||
|
||||
Это версия с критическими изменениями. Все этапы реализованы одновременно.
|
||||
|
||||
### Этап 1: Изменения схемы
|
||||
Заменить `text: str` на `texts: list[str]` в EmbeddingsRequest
|
||||
Изменить тип `vectors` на `list[list[list[float]]]` в EmbeddingsResponse
|
||||
|
||||
### Этап 2: Обновление процессоров
|
||||
Обновить сигнатуру `on_embeddings` в процессорах FastEmbed и Ollama
|
||||
Обрабатывать полный пакет за один вызов модели
|
||||
|
||||
### Этап 3: Обновление клиентской части
|
||||
Обновить `EmbeddingsClient.embed()` для приема `texts: list[str]`
|
||||
|
||||
### Этап 4: Обновление вызывающего кода
|
||||
Обновить graph_embeddings для пакетной обработки контекстов сущностей
|
||||
Обновить row_embeddings для пакетной обработки текстов индекса
|
||||
Обновить document_embeddings для использования новой схемы
|
||||
Обновить инструмент командной строки
|
||||
|
||||
### Этап 5: API-шлюз
|
||||
Обновить конечную точку для вложений в соответствии с новой схемой
|
||||
|
||||
### Этап 6: Python SDK
|
||||
Обновить сигнатуру `FlowInstance.embeddings()`
|
||||
Обновить сигнатуру `SocketFlowInstance.embeddings()`
|
||||
|
||||
## Открытые вопросы
|
||||
|
||||
**Потоковая передача больших пакетов**: Следует ли нам поддерживать потоковую передачу результатов для очень больших пакетов (>100 текстов)?
|
||||
**Ограничения, специфичные для поставщиков**: Как нам обрабатывать поставщиков с разными максимальными размерами пакетов?
|
||||
**Обработка частичных сбоев**: Если один текст в пакете завершается сбоем, следует ли нам завершать весь пакет или возвращать частичные результаты?
|
||||
**Пакетная обработка документов**: Следует ли нам выполнять пакетную обработку по нескольким сообщениям Chunk или сохранять обработку для каждого сообщения?
|
||||
|
||||
## Ссылки
|
||||
|
||||
[Документация FastEmbed](https://github.com/qdrant/fastembed)
|
||||
[API вложений Ollama](https://github.com/ollama/ollama)
|
||||
[Реализация сервиса вложений](trustgraph-base/trustgraph/base/embeddings_service.py)
|
||||
[Оптимизация производительности GraphRAG](graphrag-performance-optimization.md)
|
||||
675
docs/tech-specs/embeddings-batch-processing.sw.md
Normal file
675
docs/tech-specs/embeddings-batch-processing.sw.md
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Vipimo vya Kiufundi vya Uendeshaji wa Pamoja wa Matukio (Embeddings)"
|
||||
parent: "Swahili (Beta)"
|
||||
---
|
||||
|
||||
# Vipimo vya Kiufundi vya Uendeshaji wa Pamoja wa Matukio (Embeddings)
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Muhtasari
|
||||
|
||||
Maelekezo haya yanaelezea uboreshaji kwa huduma ya matukio ili kusaidia uendeshaji wa pamoja wa maandishi mengi katika ombi moja. Utaratibu wa sasa huendesha maandishi moja kwa wakati, na hivyo kupoteza faida kubwa za utendaji ambazo modeli za matukio hutoa wakati wa kuendesha matukio.
|
||||
|
||||
1. **Utofauti wa Uendeshaji wa Maandishi Moja**: Utaratibu wa sasa unaficha maandishi ya moja ndani ya orodha, na hivyo kutumia viboresho vya uendeshaji wa FastEmbed.
|
||||
2. **Mizio ya Ombi kwa Maandishi Kila Moja**: Maandishi kila moja yanahitaji ujumbe tofauti wa Pulsar.
|
||||
3. **Utofauti wa Uendeshaji wa Modeli**: Modeli za matukio zina gharama thabiti kwa kila kundi; madaraja madogo hutumia rasilimali za GPU/CPU.
|
||||
4. **Uendeshaji wa Mfululizo katika Huduma Zinazotumia**: Huduma muhimu huenda kupitia vipengele na kuita matukio moja kwa moja.
|
||||
|
||||
## Lengo
|
||||
|
||||
**Usaidizi wa API ya Matukio**: Kuruhusu uendeshaji wa maandishi mengi katika ombi moja.
|
||||
**Ulinganifu na Mifumo ya Zamani**: Kuendelea kutoa usaidizi kwa ombi la maandishi moja.
|
||||
**Uboreshaji Mkubwa wa Ufanisi**: Lengo ni uboreshaji wa ufanisi wa mara 5-10 kwa operesheni za jumla.
|
||||
**Kupunguza Muda wa Kila Maandishi**: Kupunguza muda wa wastani wakati wa kuendesha matukio ya maandishi mengi.
|
||||
**Ufanisi wa Kumbukumbu**: Kuendesha madaraja bila matumizi mengi ya kumbukumbu.
|
||||
**Usiohusiana na Mtoa Huduma**: Kusaidia uendeshaji wa pamoja kwa FastEmbed, Ollama, na watoa huduma wengine.
|
||||
**Kubadilisha Huduma Zinazotumia**: Kusasisha huduma zote zinazotumia matukio ili kutumia API ya matukio ambapo inafaa.
|
||||
|
||||
## Asili
|
||||
|
||||
### Utaratibu wa Sasa - Huduma ya Matukio
|
||||
|
||||
Utaratibu wa matukio katika `trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` unaonyesha upotevu mkubwa wa utendaji:
|
||||
|
||||
```python
|
||||
# fastembed/processor.py line 56
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
vecs = self.embeddings.embed([text]) # Single text wrapped in list
|
||||
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**Matatizo:**
|
||||
|
||||
1. **Ukubwa wa Kundi 1**: Njia ya `embed()` ya FastEmbed imeundwa kwa ajili ya usindikaji wa kundi, lakini tunaiita kila wakati na `[text]` - kikundi cha ukubwa wa 1.
|
||||
|
||||
2. **Mizio ya Kila Ombi**: Kila ombi la uainishaji (embedding) hutoa:
|
||||
Usajili/uondoaji wa ujumbe wa Pulsar
|
||||
Muda wa kusafiri wa mtandao (latency)
|
||||
Mizio ya kuanzisha utekelezaji wa mfumo (model inference)
|
||||
Mizio ya upangaji wa async ya Python
|
||||
|
||||
3. **Kizuia cha Mpango (Schema)**: Mpango wa `EmbeddingsRequest` unaunga mkono tu maandishi moja:
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
text: str = "" # Single text only
|
||||
```
|
||||
|
||||
### Wataalamu Wanaotumia Sasa - Uendeshaji wa Mfululizo
|
||||
|
||||
#### 1. Lango la API
|
||||
|
||||
**Faili:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
Lango linakubali ombi za uingizaji maandishi moja kupitia HTTP/WebSocket na huvipeleka kwa huduma ya uingizaji. Kwa sasa, hakuna mwisho wa kazi za kikundi.
|
||||
|
||||
```python
|
||||
class EmbeddingsRequestor(ServiceRequestor):
|
||||
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
||||
request_schema=EmbeddingsRequest, # Single text only
|
||||
response_schema=EmbeddingsResponse,
|
||||
```
|
||||
|
||||
**Athari:** Wateja wa nje (programu za wavuti, skripti) lazima wafanye ombi la HTTP N ili kuingiza maandishi N.
|
||||
|
||||
#### 2. Huduma ya Kuingiza Nyaraka
|
||||
|
||||
**Faili:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
Huprosesa vipande vya nyaraka moja kwa moja:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
v = msg.value()
|
||||
|
||||
# Single chunk per request
|
||||
resp = await flow("embeddings-request").request(
|
||||
EmbeddingsRequest(text=v.chunk)
|
||||
)
|
||||
vectors = resp.vectors
|
||||
```
|
||||
|
||||
**Athari:** Kila sehemu ya hati inahitaji ombi tofauti la uingizaji (embedding). Hati yenye sehemu 100 = ombi la uingizaji 100.
|
||||
|
||||
#### 3. Huduma ya Uingizaji wa Picha (Graph Embeddings Service)
|
||||
|
||||
**Faili:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
|
||||
Inafanya mzunguko kwenye vitu na kuingiza kila kimoja kwa mtiririko:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for entity in v.entities:
|
||||
# Serial embedding - one entity at a time
|
||||
vectors = await flow("embeddings-request").embed(
|
||||
text=entity.context
|
||||
)
|
||||
entities.append(EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors,
|
||||
chunk_id=entity.chunk_id,
|
||||
))
|
||||
```
|
||||
|
||||
**Athari:** Ujumbe wenye vitu 50 = ombi la uwekaji wa maandishi (embedding) la kila kitu. Hii ni kikwazo kikubwa wakati wa uundaji wa grafu ya maarifa.
|
||||
|
||||
#### 4. Huduma ya Uwekaji wa Maandishi ya Safu
|
||||
|
||||
**Faili:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
|
||||
Huenda kupitia maandishi ya kipekee na huweka kila moja kwa mmoja:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
# Serial embedding - one text at a time
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
|
||||
embeddings_list.append(RowIndexEmbedding(
|
||||
index_name=index_name,
|
||||
index_value=index_value,
|
||||
text=text,
|
||||
vectors=vectors
|
||||
))
|
||||
```
|
||||
|
||||
**Athari:** Kuchakata jedwali lenye maadili 100 ya kipekee yaliyopangwa = maombi 100 ya uwekaji data (embedding) kwa kila moja.
|
||||
|
||||
#### 5. EmbeddingsClient (Mteja wa Msingi)
|
||||
|
||||
**Faili:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
Mteja unaotumika na vichakataji vyote vya mtiririko unao na uwezo wa kuweka data (embedding) kwa maandishi moja tu:
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(self, text, timeout=30):
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(text=text), # Single text
|
||||
timeout=timeout
|
||||
)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
**Athari:** Wateja wote wanaotumia programu hii wamezuiliwa kufanya kazi za maandishi pekee.
|
||||
|
||||
#### 6. Vifaa vya Amri (Command-Line Tools)
|
||||
|
||||
**Faili:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
Zana ya CLI inakubali hoja moja ya maandishi:
|
||||
|
||||
```python
|
||||
def query(url, flow_id, text, token=None):
|
||||
result = flow.embeddings(text=text) # Single text
|
||||
vectors = result.get("vectors", [])
|
||||
```
|
||||
|
||||
**Athari:** Watumiaji hawawezi kuingiza data kwa wingi kupitia amri. Kuchakata faili ya maandishi inahitaji utendaji wa N mara.
|
||||
|
||||
#### 7. SDK ya Python
|
||||
|
||||
SDK ya Python hutoa madarasa mawili ya wateja kwa kuingiliana na huduma za TrustGraph. Zote mbili zinaunga mkono tu kuingiza maandishi moja.
|
||||
|
||||
**Faili:** `trustgraph-base/trustgraph/api/flow.py`
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, text):
|
||||
"""Get embeddings for a single text"""
|
||||
input = {"text": text}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**Faili:** `trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, text: str, **kwargs: Any) -> Dict[str, Any]:
|
||||
"""Get embeddings for a single text via WebSocket"""
|
||||
request = {"text": text}
|
||||
return self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
```
|
||||
|
||||
**Athari:** Wasanidi wa Python wanaotumia SDK lazima watumie mzunguko kwenye maandishi na kufanya maombi tofauti ya API. Hakuna msaada wa uingizaji wa data kwa wingi (batch) kwa watumiaji wa SDK.
|
||||
|
||||
### Athari za Utendaji
|
||||
|
||||
Kwa uingizaji wa kawaida wa hati (vifaa 1000 vya maandishi):
|
||||
**Sasa**: Maombi 1000 tofauti, matumizi 1000 ya mfumo wa utambuzi (model inference).
|
||||
**Kwa wingi (batch_size=32)**: Maombi 32, matumizi 32 ya mfumo wa utambuzi (96.8% ya kupungua).
|
||||
|
||||
Kwa uingizaji wa data kwa wingi (message na vitu 50):
|
||||
**Sasa**: Simu 50 za `await` mfululizo, takriban sekunde 5-10.
|
||||
**Kwa wingi**: Simu 1-2 za wingi, takriban sekunde 0.5-1 (uboreshaji wa mara 5-10).
|
||||
|
||||
Maktaba kama FastEmbed na zile sawa hufikia ongezeko la takriban moja kwa moja la ufanisi kwa wingi, hadi kikomo cha vifaa (kawaida vifaa 32-128 kwa wingi).
|
||||
|
||||
## Muundo wa Kiufundi
|
||||
|
||||
### Muundo
|
||||
|
||||
Uboreshaji wa uingizaji wa data kwa wingi unahitaji mabadiliko katika vipengele vifuatavyo:
|
||||
|
||||
#### 1. **Uboreshaji wa Mfumo**
|
||||
Panua `EmbeddingsRequest` ili kusaidia maandishi mengi.
|
||||
Panua `EmbeddingsResponse` ili kurejesha seti nyingi za vector.
|
||||
Dumishe utangamano na maombi ya maandishi moja.
|
||||
|
||||
Moduli: `trustgraph-base/trustgraph/schema/services/llm.py`
|
||||
|
||||
#### 2. **Uboreshaji wa Huduma ya Msingi**
|
||||
Sasisha `EmbeddingsService` ili kushughulikia maombi ya wingi.
|
||||
Ongeza usanidi wa ukubwa wa wingi.
|
||||
Lenga ushughulikiaji wa maombi unaoelinganisha na wingi.
|
||||
|
||||
Moduli: `trustgraph-base/trustgraph/base/embeddings_service.py`
|
||||
|
||||
#### 3. **Sasisho za Mchakato wa Mtoa Huduma**
|
||||
Sasisha mchakato wa FastEmbed ili kupitisha wingi kamili kwa `embed()`.
|
||||
Sasisha mchakato wa Ollama ili kushughulikia wingi (ikiwa inasaidiwa).
|
||||
Ongeza ushughulikiaji wa mfululizo kama njia ya dharura kwa watoa huduma ambao hawasaidii wingi.
|
||||
|
||||
Moduli:
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
||||
|
||||
#### 4. **Uboreshaji kwa Mteja**
|
||||
Ongeza njia ya kuingiza data kwa wingi katika `EmbeddingsClient`
|
||||
Saidia API za moja kwa moja na za wingi
|
||||
Ongeza uingizaji wa data kwa wingi kwa data kubwa
|
||||
|
||||
Moduli: `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
#### 5. **Sasisho kwa Msimuizi - Wasindikaji wa Mchakato**
|
||||
Sasisha `graph_embeddings` ili kuingiza muktadha wa vitu kwa wingi
|
||||
Sasisha `row_embeddings` ili kuingiza maandishi ya faharasa kwa wingi
|
||||
Sasisha `document_embeddings` ikiwa uingizaji wa data kwa wingi unawezekana
|
||||
|
||||
Moduli:
|
||||
`trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
#### 6. **Uboreshaji kwa Lango la API**
|
||||
Ongeza mwisho wa kuingiza data kwa wingi
|
||||
Saidia safu ya maandishi katika mwili wa ombi
|
||||
|
||||
Moduli: `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
#### 7. **Uboreshaji kwa Zana ya CLI**
|
||||
Ongeza usaidizi wa maandishi mengi au uingizaji wa faili
|
||||
Ongeza parameter ya ukubwa wa wingi
|
||||
|
||||
Moduli: `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
#### 8. **Uboreshaji kwa SDK ya Python**
|
||||
Ongeza njia ya `embeddings_batch()` katika `FlowInstance`
|
||||
Ongeza njia ya `embeddings_batch()` katika `SocketFlowInstance`
|
||||
Saidia API za moja kwa moja na za wingi kwa watumiaji wa SDK
|
||||
|
||||
Moduli:
|
||||
`trustgraph-base/trustgraph/api/flow.py`
|
||||
`trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
### Mifano ya Data
|
||||
|
||||
#### EmbeddingsRequest
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Matumizi:
|
||||
Nakala moja: `EmbeddingsRequest(texts=["hello world"])`
|
||||
Kundi: `EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
||||
|
||||
#### Jibu la Uelekezaji
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Muundo wa majibu:
|
||||
`vectors[i]` ina mkusanyiko wa vektali kwa `texts[i]`
|
||||
Kila mkusanyiko wa vektali ni `list[list[float]]` (modeli zinaweza kurejesha vektali nyingi kwa kila maandishi)
|
||||
Kwa mfano: maandishi 3 → `vectors` ina vipengele 3, kila kipengele kina uelekezo wa maandishi hayo
|
||||
|
||||
### API
|
||||
|
||||
#### EmbeddingsClient
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(
|
||||
self,
|
||||
texts: list[str],
|
||||
timeout: float = 300,
|
||||
) -> list[list[list[float]]]:
|
||||
"""
|
||||
Embed one or more texts in a single request.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
timeout: Timeout for the operation
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(texts=texts),
|
||||
timeout=timeout
|
||||
)
|
||||
if resp.error:
|
||||
raise RuntimeError(resp.error.message)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
#### Ncha ya Ufikiaji (Endpoint) ya Uingizaji (Embedding) ya Langara ya API
|
||||
|
||||
Ncha ya ufikiaji (endpoint) imesasishwa ili kusaidia uingizaji (embedding) mmoja au wa kikundi:
|
||||
|
||||
```
|
||||
POST /api/v1/embeddings
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"texts": ["text1", "text2", "text3"],
|
||||
"flow_id": "default"
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"vectors": [
|
||||
[[0.1, 0.2, ...]],
|
||||
[[0.3, 0.4, ...]],
|
||||
[[0.5, 0.6, ...]]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Maelezo ya Utendaji
|
||||
|
||||
#### Awamu ya 1: Marekebisho ya Mfumo
|
||||
|
||||
**Ombi la Uingizaji:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**Jibu la Uingizwaji:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**Sasisho la `EmbeddingsService.on_request`:**
|
||||
```python
|
||||
async def on_request(self, msg, consumer, flow):
|
||||
request = msg.value()
|
||||
id = msg.properties()["id"]
|
||||
model = flow("model")
|
||||
|
||||
vectors = await self.on_embeddings(request.texts, model=model)
|
||||
response = EmbeddingsResponse(error=None, vectors=vectors)
|
||||
|
||||
await flow("response").send(response, properties={"id": id})
|
||||
```
|
||||
|
||||
#### Awamu ya 2: Sasisho la Mchakato wa FastEmbed
|
||||
|
||||
**Sasa (Haina ufanisi):**
|
||||
```python
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
vecs = self.embeddings.embed([text]) # Batch of 1
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**Imebhadiliwa:**
|
||||
```python
|
||||
async def on_embeddings(self, texts: list[str], model=None):
|
||||
"""Embed texts - processes all texts in single model call"""
|
||||
if not texts:
|
||||
return []
|
||||
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
# FastEmbed handles the full batch efficiently
|
||||
all_vecs = list(self.embeddings.embed(texts))
|
||||
|
||||
# Return list of vector sets, one per input text
|
||||
return [[v.tolist()] for v in all_vecs]
|
||||
```
|
||||
|
||||
#### Awamu ya 3: Sasisho la Huduma ya Uingizaji Picha kwenye Grafu
|
||||
|
||||
**Sasa (Mfululizo):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
entities = []
|
||||
for entity in v.entities:
|
||||
vectors = await flow("embeddings-request").embed(text=entity.context)
|
||||
entities.append(EntityEmbeddings(...))
|
||||
```
|
||||
|
||||
**Imebhadilishwa (Kundi):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
# Collect all contexts
|
||||
contexts = [entity.context for entity in v.entities]
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=contexts)
|
||||
|
||||
# Pair results with entities
|
||||
entities = [
|
||||
EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors[0], # First vector from the set
|
||||
chunk_id=entity.chunk_id,
|
||||
)
|
||||
for entity, vectors in zip(v.entities, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### Awamu ya 4: Sasisho la Huduma ya Uwekaji Data katika Safu
|
||||
|
||||
**Sasa (Mfululizo):**
|
||||
```python
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
embeddings_list.append(RowIndexEmbedding(...))
|
||||
```
|
||||
|
||||
**Imebhadilishwa (Kundi):**
|
||||
```python
|
||||
# Collect texts and metadata
|
||||
texts = list(texts_to_embed.keys())
|
||||
metadata = list(texts_to_embed.values())
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=texts)
|
||||
|
||||
# Pair results
|
||||
embeddings_list = [
|
||||
RowIndexEmbedding(
|
||||
index_name=meta[0],
|
||||
index_value=meta[1],
|
||||
text=text,
|
||||
vectors=vectors[0] # First vector from the set
|
||||
)
|
||||
for text, meta, vectors in zip(texts, metadata, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### Awamu ya 5: Kuboresha Zana ya Kifaa cha Amri (CLI)
|
||||
|
||||
**CLI iliyoboreshwa:**
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(...)
|
||||
|
||||
parser.add_argument(
|
||||
'text',
|
||||
nargs='*', # Zero or more texts
|
||||
help='Text(s) to convert to embedding vectors',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--file',
|
||||
help='File containing texts (one per line)',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--batch-size',
|
||||
type=int,
|
||||
default=32,
|
||||
help='Batch size for processing (default: 32)',
|
||||
)
|
||||
```
|
||||
|
||||
Matumizi:
|
||||
```bash
|
||||
# Single text (existing)
|
||||
tg-invoke-embeddings "hello world"
|
||||
|
||||
# Multiple texts
|
||||
tg-invoke-embeddings "text one" "text two" "text three"
|
||||
|
||||
# From file
|
||||
tg-invoke-embeddings -f texts.txt --batch-size 64
|
||||
```
|
||||
|
||||
#### Awamu ya 6: Kuboresha Kitengo cha Programu (SDK) cha Python
|
||||
|
||||
**FlowInstance (mfumo wa wateja wa HTTP):**
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, texts: list[str]) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
input = {"texts": texts}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**SocketFlowInstance (mfumo wa mteja wa WebSocket):**
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts via WebSocket.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
request = {"texts": texts}
|
||||
response = self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
return response["vectors"]
|
||||
```
|
||||
|
||||
**Mfano wa Matumizi ya SDK:**
|
||||
|
||||
```python
|
||||
# Single text
|
||||
vectors = flow.embeddings(["hello world"])
|
||||
print(f"Dimensions: {len(vectors[0][0])}")
|
||||
|
||||
# Batch embedding
|
||||
texts = ["text one", "text two", "text three"]
|
||||
all_vectors = flow.embeddings(texts)
|
||||
|
||||
# Process results
|
||||
for text, vecs in zip(texts, all_vectors):
|
||||
print(f"{text}: {len(vecs[0])} dimensions")
|
||||
```
|
||||
|
||||
## Mambo ya Kuzingatia Kuhusu Usalama
|
||||
|
||||
**Vikomo vya Ukubwa wa Ombi**: Punguza ukubwa wa juu wa kila kikundi ili kuzuia matumizi yasiyofaa ya rasilimali.
|
||||
**Usimamizi wa Muda wa Hesabu (Timeout)**: Punguza muda wa hesabu ipasavyo kwa ukubwa wa kikundi.
|
||||
**Vikomo vya Kumbukumbu**: Fuatilia matumizi ya kumbukumbu kwa vikundi vikubwa.
|
||||
**Uthibitisho wa Pembejeo**: Thibitisha maandishi yote katika kikundi kabla ya kuchakata.
|
||||
|
||||
## Mambo ya Kuzingatia Kuhusu Utendaji
|
||||
|
||||
### Ubora Unaotarajiwa
|
||||
|
||||
**Uwezo wa Kuchakata (Throughput):**
|
||||
Maandishi moja: ~10-50 maandishi/sekunde (kulingana na mfumo)
|
||||
Kikundi (ukubwa wa 32): ~200-500 maandishi/sekunde (uboreshaji wa 5-10x)
|
||||
|
||||
**Muda wa Kuchakata Kila Maandishi:**
|
||||
Maandishi moja: 50-200ms kwa kila maandishi
|
||||
Kikundi (ukubwa wa 32): 5-20ms kwa kila maandishi (kwa wastani)
|
||||
|
||||
**Ubora Maalum kwa Huduma:**
|
||||
|
||||
| Huduma | Sasa | Kwa Kikundi | Uboreshaji |
|
||||
|---------|---------|---------|-------------|
|
||||
| Uwekaji Picha (50 vitu) | 5-10s | 0.5-1s | 5-10x |
|
||||
| Uwekaji Mistari (100 maandishi) | 10-20s | 1-2s | 5-10x |
|
||||
| Uingizaji wa Hati (1000 sehemu) | 100-200s | 10-30s | 5-10x |
|
||||
|
||||
### Vigezo vya Usanidi
|
||||
|
||||
```python
|
||||
# Recommended defaults
|
||||
DEFAULT_BATCH_SIZE = 32
|
||||
MAX_BATCH_SIZE = 128
|
||||
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
||||
```
|
||||
|
||||
## Mbinu ya Majaribio
|
||||
|
||||
### Majaribio ya Kitengo
|
||||
Uingizaji wa maandishi moja (utangamano wa nyuma)
|
||||
Usimamizi wa kundi tupu
|
||||
Utumiaji wa ukubwa wa juu wa kundi
|
||||
Usimamizi wa makosa kwa kushindwa kwa kundi
|
||||
|
||||
### Majaribio ya Uunganisho
|
||||
Uingizaji wa kundi kamili kupitia Pulsar
|
||||
Uchakataji wa kundi wa huduma ya uingizaji wa grafu
|
||||
Uchakataji wa kundi wa huduma ya uingizaji wa mstari
|
||||
Ncha ya kundi ya lango la API
|
||||
|
||||
### Majaribio ya Utendaji
|
||||
Tathmini ya kasi ya uingizaji wa moja dhidi ya kundi
|
||||
Matumizi ya kumbukumbu chini ya saizi tofauti za kundi
|
||||
Uchambuzi wa usambazaji wa kuchelewesha
|
||||
|
||||
## Mpango wa Uhamisho
|
||||
|
||||
Hii ni toleo la mabadiliko makubwa. Awamu zote zinafanywa pamoja.
|
||||
|
||||
### Awamu ya 1: Mabadiliko ya Mpango
|
||||
Badilisha `text: str` na `texts: list[str]` katika EmbeddingsRequest
|
||||
Badilisha aina ya `vectors` kuwa `list[list[list[float]]]` katika EmbeddingsResponse
|
||||
|
||||
### Awamu ya 2: Masuala ya Marekebisho
|
||||
Sasisha saini ya `on_embeddings` katika washauri wa FastEmbed na Ollama
|
||||
Chakata kundi kamili katika wito mmoja wa modeli
|
||||
|
||||
### Awamu ya 3: Masuala ya Wateja
|
||||
Sasisha `EmbeddingsClient.embed()` ili kukubali `texts: list[str]`
|
||||
|
||||
### Awamu ya 4: Watumiaji
|
||||
Sasisha graph_embeddings ili kuingiza muktadha wa vitu katika kundi
|
||||
Sasisha row_embeddings ili kuingiza maandishi ya faharasa katika kundi
|
||||
Sasisha document_embeddings ili itumie mpango mpya
|
||||
Sasisha zana ya CLI
|
||||
|
||||
### Awamu ya 5: Lango la API
|
||||
Sasisha ncha ya uingizaji kwa mpango mpya
|
||||
|
||||
### Awamu ya 6: SDK ya Python
|
||||
Sasisha saini ya `FlowInstance.embeddings()`
|
||||
Sasisha saini ya `SocketFlowInstance.embeddings()`
|
||||
|
||||
## Maswali ya Funguo
|
||||
|
||||
**Uingizaji wa Kundi Kubwa**: Je, tunapaswa kusaidia uingizaji wa matokeo kwa kundi kubwa sana (>100 maandishi)?
|
||||
**Vikomo Maalum vya Mtoa Huduma**: Je, tunapaswa kushughulikia watoa huduma wenye saizi tofauti za kundi?
|
||||
**Usimamizi wa Kushindwa kwa Kiasi**: Ikiwa maandishi moja katika kundi kushindwa, je, tunapaswa kushindwa kundi lote au kurudisha matokeo ya sehemu?
|
||||
**Uingizaji wa Kundi wa Mengine**: Je, tunapaswa kuingiza kote kwa ujumbe mwingi wa Chunk au kuendelea na uchakataji wa kila ujumbe?
|
||||
|
||||
## Marejeleo
|
||||
|
||||
[Dokumenti ya FastEmbed](https://github.com/qdrant/fastembed)
|
||||
[API ya Uingizaji ya Ollama](https://github.com/ollama/ollama)
|
||||
[Utekelezaji wa Huduma ya Uingizaji](trustgraph-base/trustgraph/base/embeddings_service.py)
|
||||
[Uboreshaji wa Utendaji wa GraphRAG](graphrag-performance-optimization.md)
|
||||
675
docs/tech-specs/embeddings-batch-processing.tr.md
Normal file
675
docs/tech-specs/embeddings-batch-processing.tr.md
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Gömme İşlemleri Toplu İşleme Teknik Özellikleri"
|
||||
parent: "Turkish (Beta)"
|
||||
---
|
||||
|
||||
# Gömme İşlemleri Toplu İşleme Teknik Özellikleri
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Genel Bakış
|
||||
|
||||
Bu teknik özellik, gömme hizmeti için, tek bir istekte birden fazla metni toplu olarak işleyebilmeyi desteklemek amacıyla yapılan optimizasyonları açıklamaktadır. Mevcut uygulama, her seferinde tek bir metni işlemektedir ve bu durum, gömme modellerinin toplu işlemler sırasında sağladığı önemli performans avantajlarından yararlanılmamasına neden olmaktadır.
|
||||
|
||||
1. **Tek Metin İşleme Verimsizliği**: Mevcut uygulama, tek metinleri bir liste içinde kullanarak, FastEmbed'in toplu işleme yeteneklerini tam olarak kullanamamaktadır.
|
||||
2. **Metin Başına İstek Yükü**: Her metin için ayrı bir Pulsar mesajı gönderilip alınması gerekmektedir.
|
||||
3. **Model Çıkarım Verimsizliği**: Gömme modellerinin sabit bir toplu işleme yükü vardır; küçük toplu işlemler GPU/CPU kaynaklarının israfına yol açar.
|
||||
4. **Çağıran Tarafında Seri İşleme**: Önemli hizmetler, öğeler üzerinde döngü yaparak gömme işlemlerini tek tek gerçekleştirmektedir.
|
||||
|
||||
## Hedefler
|
||||
|
||||
**Toplu API Desteği**: Tek bir istekte birden fazla metni işleyebilmeyi destekleyin.
|
||||
**Geriye Dönük Uyumluluk**: Tek metin isteklerine olan desteği koruyun.
|
||||
**Önemli Verimlilik Artışı**: Toplu işlemler için 5-10 kat verimlilik artışı hedefleyin.
|
||||
**Metin Başına Azaltılmış Gecikme**: Birden fazla metni gömme işlemi sırasında amortize gecikmeyi azaltın.
|
||||
**Bellek Verimliliği**: Aşırı bellek tüketimi olmadan toplu işlemleri gerçekleştirin.
|
||||
**Sağlayıcıdan Bağımsızlık**: FastEmbed, Ollama ve diğer sağlayıcılar arasında toplu işleme desteğini sağlayın.
|
||||
**Çağıran Taraf Güncellemesi**: Toplu API'nin faydalı olduğu durumlarda tüm gömme işlemlerini kullanan hizmetleri güncelleyin.
|
||||
|
||||
## Arka Plan
|
||||
|
||||
### Mevcut Uygulama - Gömme Hizmeti
|
||||
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` içindeki gömme uygulamasında önemli bir performans verimsizliği bulunmaktadır:
|
||||
|
||||
```python
|
||||
# fastembed/processor.py line 56
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
vecs = self.embeddings.embed([text]) # Single text wrapped in list
|
||||
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**Sorunlar:**
|
||||
|
||||
1. **Batch Boyutu 1:** FastEmbed'in `embed()` yöntemi, toplu işleme için optimize edilmiştir, ancak bunu her zaman `[text]` - 1 boyutlu bir toplu işleme ile çağırıyoruz.
|
||||
|
||||
2. **İstek Başına Ek Yük:** Her gömme isteği aşağıdaki ek yükleri içerir:
|
||||
Pulsar mesajı serileştirme/deserileştirme
|
||||
Ağ gidiş-dönüş gecikmesi
|
||||
Model çıkarım başlatma ek yükü
|
||||
Python asenkron planlama ek yükü
|
||||
|
||||
3. **Şema Sınırlaması:** `EmbeddingsRequest` şeması yalnızca tek bir metni destekler:
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
text: str = "" # Single text only
|
||||
```
|
||||
|
||||
### Mevcut Çağrılar - Seri İşleme
|
||||
|
||||
#### 1. API Ağ Geçidi
|
||||
|
||||
**Dosya:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
Ağ geçidi, HTTP/WebSocket üzerinden tek metin gömme isteklerini kabul eder ve bunları gömme hizmetine yönlendirir. Şu anda toplu işlem için bir uç nokta bulunmamaktadır.
|
||||
|
||||
```python
|
||||
class EmbeddingsRequestor(ServiceRequestor):
|
||||
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
||||
request_schema=EmbeddingsRequest, # Single text only
|
||||
response_schema=EmbeddingsResponse,
|
||||
```
|
||||
|
||||
**Etki:** Harici müşteriler (web uygulamaları, betikler), N metni yerleştirmek için N adet HTTP isteği yapmalıdır.
|
||||
|
||||
#### 2. Belge Gömme Hizmeti
|
||||
|
||||
**Dosya:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
Belgeleri tek tek parçalar halinde işler:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
v = msg.value()
|
||||
|
||||
# Single chunk per request
|
||||
resp = await flow("embeddings-request").request(
|
||||
EmbeddingsRequest(text=v.chunk)
|
||||
)
|
||||
vectors = resp.vectors
|
||||
```
|
||||
|
||||
**Etki:** Her belge parçası için ayrı bir gömme (embedding) çağrısı gereklidir. 100 parçadan oluşan bir belge = 100 gömme isteği.
|
||||
|
||||
#### 3. Grafik Gömme Hizmeti
|
||||
|
||||
**Dosya:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
|
||||
Varlıklar üzerinde döngü yapar ve her birini sırayla gömer:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for entity in v.entities:
|
||||
# Serial embedding - one entity at a time
|
||||
vectors = await flow("embeddings-request").embed(
|
||||
text=entity.context
|
||||
)
|
||||
entities.append(EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors,
|
||||
chunk_id=entity.chunk_id,
|
||||
))
|
||||
```
|
||||
|
||||
**Etki:** 50 varlık içeren bir mesaj, 50 adet ardışık gömme (embedding) isteği anlamına gelir. Bu, bilgi grafiği oluşturma sırasında büyük bir darboğazdır.
|
||||
|
||||
#### 4. Satır Gömme Hizmeti
|
||||
|
||||
**Dosya:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
|
||||
Benzersiz metinler üzerinde döngü yapar ve her birini sırayla gömer:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
# Serial embedding - one text at a time
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
|
||||
embeddings_list.append(RowIndexEmbedding(
|
||||
index_name=index_name,
|
||||
index_value=index_value,
|
||||
text=text,
|
||||
vectors=vectors
|
||||
))
|
||||
```
|
||||
|
||||
**Etki:** 100 benzersiz indeksli değere sahip bir tabloyu işlemek = 100 ardışık gömme isteği.
|
||||
|
||||
#### 5. EmbeddingsClient (Temel İstemci)
|
||||
|
||||
**Dosya:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
Tüm iş akışı işleyicileri tarafından kullanılan istemci, yalnızca tek metin gömmesini destekler:
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(self, text, timeout=30):
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(text=text), # Single text
|
||||
timeout=timeout
|
||||
)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
**Etki:** Bu istemciyi kullanan tüm uygulamalar, yalnızca tek metin işlemleriyle sınırlıdır.
|
||||
|
||||
#### 6. Komut Satırı Araçları
|
||||
|
||||
**Dosya:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
CLI aracı, tek bir metin argümanı alır:
|
||||
|
||||
```python
|
||||
def query(url, flow_id, text, token=None):
|
||||
result = flow.embeddings(text=text) # Single text
|
||||
vectors = result.get("vectors", [])
|
||||
```
|
||||
|
||||
**Etki:** Kullanıcılar, komut satırından toplu gömme işlemi yapamaz. Bir metin dosyasını işlemek, N sayıda çağrı gerektirir.
|
||||
|
||||
#### 7. Python SDK
|
||||
|
||||
Python SDK, TrustGraph hizmetleriyle etkileşim kurmak için iki istemci sınıfı sağlar. Her ikisi de yalnızca tek metin gömme işlemini destekler.
|
||||
|
||||
**Dosya:** `trustgraph-base/trustgraph/api/flow.py`
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, text):
|
||||
"""Get embeddings for a single text"""
|
||||
input = {"text": text}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**Dosya:** `trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, text: str, **kwargs: Any) -> Dict[str, Any]:
|
||||
"""Get embeddings for a single text via WebSocket"""
|
||||
request = {"text": text}
|
||||
return self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
```
|
||||
|
||||
**Etki:** SDK'yı kullanan Python geliştiricilerinin, metinler üzerinde döngü yapması ve N adet API çağrısı yapması gerekir. SDK kullanıcıları için toplu gömme desteği mevcut değildir.
|
||||
|
||||
### Performans Etkisi
|
||||
|
||||
Tipik belge yükleme için (1000 metin parçası):
|
||||
**Mevcut:** 1000 ayrı istek, 1000 model çıkarım çağrısı
|
||||
**Toplu (batch_size=32):** 32 istek, 32 model çıkarım çağrısı (%96,8 azalma)
|
||||
|
||||
Grafik gömme için (50 varlığa sahip mesaj):
|
||||
**Mevcut:** 50 ardışık bekletme çağrısı, ~5-10 saniye
|
||||
**Toplu:** 1-2 toplu çağrı, ~0,5-1 saniye (5-10 kat iyileşme)
|
||||
|
||||
FastEmbed ve benzeri kütüphaneler, toplu boyutun donanım sınırlarına kadar ulaştığı durumlarda, yaklaşık doğrusal bir verim ölçeklemesi sağlar (tipik olarak toplu boyutta 32-128 metin).
|
||||
|
||||
## Teknik Tasarım
|
||||
|
||||
### Mimari
|
||||
|
||||
Gömme toplu işleme optimizasyonu, aşağıdaki bileşenlerde değişiklikler gerektirir:
|
||||
|
||||
#### 1. **Şema Geliştirme**
|
||||
`EmbeddingsRequest`'ı, birden fazla metni destekleyecek şekilde genişletin
|
||||
`EmbeddingsResponse`'ı, birden fazla vektör kümesini döndürecek şekilde genişletin
|
||||
Tek metin istekleriyle uyumluluğu koruyun
|
||||
|
||||
Modül: `trustgraph-base/trustgraph/schema/services/llm.py`
|
||||
|
||||
#### 2. **Temel Servis Geliştirme**
|
||||
`EmbeddingsService`'ı, toplu istekleri işleyebilecek şekilde güncelleyin
|
||||
Toplu boyut yapılandırması ekleyin
|
||||
Toplu işleme duyarlı istek işleme uygulayın
|
||||
|
||||
Modül: `trustgraph-base/trustgraph/base/embeddings_service.py`
|
||||
|
||||
#### 3. **Sağlayıcı İşlemcisi Güncellemeleri**
|
||||
FastEmbed işlemcisini güncelleyin, böylece tam toplu iş yükünü `embed()`'a iletebilir
|
||||
Ollama işlemcisini güncelleyin, böylece toplu işlemleri işleyebilir (destekleniyorsa)
|
||||
Toplu işlemeyi desteklemeyen sağlayıcılar için yedek sıralı işlemeyi ekleyin
|
||||
|
||||
Modüller:
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
||||
|
||||
#### 4. **İstemci Geliştirme**
|
||||
`EmbeddingsClient`'a toplu gömme yöntemini ekleyin
|
||||
Hem tek hem de toplu API'leri destekleyin
|
||||
Büyük girdiler için otomatik toplu işlemeyi ekleyin
|
||||
|
||||
Modül: `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
#### 5. **Çağrı Güncellemeleri - Akış İşlemcileri**
|
||||
`graph_embeddings`'ı, varlık bağlamlarını toplu hale getirecek şekilde güncelleyin
|
||||
`row_embeddings`'ı, indeks metinlerini toplu hale getirecek şekilde güncelleyin
|
||||
Mesaj toplu işlemesi mümkünse, `document_embeddings`'ı güncelleyin
|
||||
|
||||
Modüller:
|
||||
`trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
#### 6. **API Ağ Geçidi Geliştirme**
|
||||
Toplu gömme uç noktası ekleyin
|
||||
İstek gövdesinde metin dizisini destekleyin
|
||||
|
||||
Modül: `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
#### 7. **CLI Aracı Geliştirme**
|
||||
Birden fazla metin veya dosya girişi desteği ekleyin
|
||||
Toplu boyut parametresi ekleyin
|
||||
|
||||
Modül: `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
#### 8. **Python SDK Geliştirme**
|
||||
`embeddings_batch()` yöntemini `FlowInstance`'e ekleyin
|
||||
`embeddings_batch()` yöntemini `SocketFlowInstance`'e ekleyin
|
||||
SDK kullanıcıları için hem tek hem de toplu API'leri destekleyin
|
||||
|
||||
Modüller:
|
||||
`trustgraph-base/trustgraph/api/flow.py`
|
||||
`trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
### Veri Modelleri
|
||||
|
||||
#### EmbeddingsRequest
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Kullanım:
|
||||
Tek metin: `EmbeddingsRequest(texts=["hello world"])`
|
||||
Toplu işlem: `EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
||||
|
||||
#### EmbeddingsResponse
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
Yanıt yapısı:
|
||||
`vectors[i]`, `texts[i]` için vektör kümesini içerir.
|
||||
Her vektör kümesi `list[list[float]]`'dır (modeller, her metin için birden fazla vektör döndürebilir).
|
||||
Örnek: 3 metin → `vectors`, 3 giriş içerir ve her giriş, o metnin gömülme değerlerini içerir.
|
||||
|
||||
### API'ler
|
||||
|
||||
#### EmbeddingsClient
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(
|
||||
self,
|
||||
texts: list[str],
|
||||
timeout: float = 300,
|
||||
) -> list[list[list[float]]]:
|
||||
"""
|
||||
Embed one or more texts in a single request.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
timeout: Timeout for the operation
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(texts=texts),
|
||||
timeout=timeout
|
||||
)
|
||||
if resp.error:
|
||||
raise RuntimeError(resp.error.message)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
#### API Gateway Gömülü Veri (Embeddings) Uç Noktası
|
||||
|
||||
Tek bir veya toplu gömülü veri desteğini sağlayan güncellenmiş uç nokta:
|
||||
|
||||
```
|
||||
POST /api/v1/embeddings
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"texts": ["text1", "text2", "text3"],
|
||||
"flow_id": "default"
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"vectors": [
|
||||
[[0.1, 0.2, ...]],
|
||||
[[0.3, 0.4, ...]],
|
||||
[[0.5, 0.6, ...]]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Uygulama Detayları
|
||||
|
||||
#### Aşama 1: Şema Değişiklikleri
|
||||
|
||||
**EmbeddingsRequest:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**Gömme Yanıtı:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**Güncellenmiş EmbeddingsService.on_request:**
|
||||
```python
|
||||
async def on_request(self, msg, consumer, flow):
|
||||
request = msg.value()
|
||||
id = msg.properties()["id"]
|
||||
model = flow("model")
|
||||
|
||||
vectors = await self.on_embeddings(request.texts, model=model)
|
||||
response = EmbeddingsResponse(error=None, vectors=vectors)
|
||||
|
||||
await flow("response").send(response, properties={"id": id})
|
||||
```
|
||||
|
||||
#### 2. Aşama: FastEmbed İşlemci Güncellemesi
|
||||
|
||||
**Mevcut (Verimsiz):**
|
||||
```python
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
vecs = self.embeddings.embed([text]) # Batch of 1
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**Güncellendi:**
|
||||
```python
|
||||
async def on_embeddings(self, texts: list[str], model=None):
|
||||
"""Embed texts - processes all texts in single model call"""
|
||||
if not texts:
|
||||
return []
|
||||
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
# FastEmbed handles the full batch efficiently
|
||||
all_vecs = list(self.embeddings.embed(texts))
|
||||
|
||||
# Return list of vector sets, one per input text
|
||||
return [[v.tolist()] for v in all_vecs]
|
||||
```
|
||||
|
||||
#### 3. Aşama: Grafik Gömme Hizmeti Güncellemesi
|
||||
|
||||
**Mevcut (Sıralı):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
entities = []
|
||||
for entity in v.entities:
|
||||
vectors = await flow("embeddings-request").embed(text=entity.context)
|
||||
entities.append(EntityEmbeddings(...))
|
||||
```
|
||||
|
||||
**Güncellendi (Toplu İşlem):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
# Collect all contexts
|
||||
contexts = [entity.context for entity in v.entities]
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=contexts)
|
||||
|
||||
# Pair results with entities
|
||||
entities = [
|
||||
EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors[0], # First vector from the set
|
||||
chunk_id=entity.chunk_id,
|
||||
)
|
||||
for entity, vectors in zip(v.entities, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### 4. Aşama: Satır Gömme Hizmeti Güncellemesi
|
||||
|
||||
**Mevcut (Sıralı):**
|
||||
```python
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
embeddings_list.append(RowIndexEmbedding(...))
|
||||
```
|
||||
|
||||
**Güncellendi (Toplu İşlem):**
|
||||
```python
|
||||
# Collect texts and metadata
|
||||
texts = list(texts_to_embed.keys())
|
||||
metadata = list(texts_to_embed.values())
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=texts)
|
||||
|
||||
# Pair results
|
||||
embeddings_list = [
|
||||
RowIndexEmbedding(
|
||||
index_name=meta[0],
|
||||
index_value=meta[1],
|
||||
text=text,
|
||||
vectors=vectors[0] # First vector from the set
|
||||
)
|
||||
for text, meta, vectors in zip(texts, metadata, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### 5. Aşama: Komut Satırı Arama Aracı Geliştirme
|
||||
|
||||
**Güncellenmiş Komut Satırı:**
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(...)
|
||||
|
||||
parser.add_argument(
|
||||
'text',
|
||||
nargs='*', # Zero or more texts
|
||||
help='Text(s) to convert to embedding vectors',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--file',
|
||||
help='File containing texts (one per line)',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--batch-size',
|
||||
type=int,
|
||||
default=32,
|
||||
help='Batch size for processing (default: 32)',
|
||||
)
|
||||
```
|
||||
|
||||
Kullanım:
|
||||
```bash
|
||||
# Single text (existing)
|
||||
tg-invoke-embeddings "hello world"
|
||||
|
||||
# Multiple texts
|
||||
tg-invoke-embeddings "text one" "text two" "text three"
|
||||
|
||||
# From file
|
||||
tg-invoke-embeddings -f texts.txt --batch-size 64
|
||||
```
|
||||
|
||||
#### 6. Aşama: Python SDK Geliştirme
|
||||
|
||||
**FlowInstance (HTTP istemcisi):**
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, texts: list[str]) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
input = {"texts": texts}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**SocketFlowInstance (WebSocket istemcisi):**
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts via WebSocket.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
request = {"texts": texts}
|
||||
response = self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
return response["vectors"]
|
||||
```
|
||||
|
||||
**SDK Kullanım Örnekleri:**
|
||||
|
||||
```python
|
||||
# Single text
|
||||
vectors = flow.embeddings(["hello world"])
|
||||
print(f"Dimensions: {len(vectors[0][0])}")
|
||||
|
||||
# Batch embedding
|
||||
texts = ["text one", "text two", "text three"]
|
||||
all_vectors = flow.embeddings(texts)
|
||||
|
||||
# Process results
|
||||
for text, vecs in zip(texts, all_vectors):
|
||||
print(f"{text}: {len(vecs[0])} dimensions")
|
||||
```
|
||||
|
||||
## Güvenlik Hususları
|
||||
|
||||
**İstek Boyutu Sınırları**: Kaynak tükenmesini önlemek için maksimum toplu işlem boyutunu zorlayın.
|
||||
**Zaman Aşımı İşleme**: Toplu işlem boyutu için zaman aşımını uygun şekilde ayarlayın.
|
||||
**Bellek Sınırları**: Büyük toplu işlemler için bellek kullanımını izleyin.
|
||||
**Giriş Doğrulama**: İşleme yapmadan önce toplu işlemdeki tüm metinleri doğrulayın.
|
||||
|
||||
## Performans Hususları
|
||||
|
||||
### Beklenen İyileştirmeler
|
||||
|
||||
**Verim:**
|
||||
Tek metin: ~10-50 metin/saniye (modele bağlı olarak)
|
||||
Toplu işlem (boyut 32): ~200-500 metin/saniye (5-10 kat iyileşme)
|
||||
|
||||
**Metin Başına Gecikme:**
|
||||
Tek metin: metin başına 50-200 ms
|
||||
Toplu işlem (boyut 32): metin başına 5-20 ms (ortalama)
|
||||
|
||||
**Hizmete Özel İyileştirmeler:**
|
||||
|
||||
| Hizmet | Mevcut | Toplu | İyileşme |
|
||||
|---------|---------|---------|-------------|
|
||||
| Grafik Gömme (50 varlık) | 5-10 saniye | 0,5-1 saniye | 5-10 kat |
|
||||
| Satır Gömme (100 metin) | 10-20 saniye | 1-2 saniye | 5-10 kat |
|
||||
| Belge Alma (1000 parça) | 100-200 saniye | 10-30 saniye | 5-10 kat |
|
||||
|
||||
### Yapılandırma Parametreleri
|
||||
|
||||
```python
|
||||
# Recommended defaults
|
||||
DEFAULT_BATCH_SIZE = 32
|
||||
MAX_BATCH_SIZE = 128
|
||||
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
||||
```
|
||||
|
||||
## Test Stratejisi
|
||||
|
||||
### Birim Testleri
|
||||
Tek metin gömülmesi (geriye dönük uyumluluk)
|
||||
Boş toplu iş işleme
|
||||
Maksimum toplu iş boyutu zorlaması
|
||||
Kısmi toplu iş hataları için hata işleme
|
||||
|
||||
### Entegrasyon Testleri
|
||||
Pulsar üzerinden uçtan uca toplu iş gömülmesi
|
||||
Grafik gömme hizmeti toplu iş işleme
|
||||
Satır gömme hizmeti toplu iş işleme
|
||||
API ağ geçidi toplu iş uç noktası
|
||||
|
||||
### Performans Testleri
|
||||
Tek ve toplu iş verimini karşılaştırma
|
||||
Farklı toplu iş boyutları altındaki bellek kullanımı
|
||||
Gecikme dağılımı analizi
|
||||
|
||||
## Geçiş Planı
|
||||
|
||||
Bu, önemli değişikliklere neden olan bir sürümdür. Tüm fazlar birlikte uygulanır.
|
||||
|
||||
### 1. Aşama: Şema Değişiklikleri
|
||||
EmbeddingsRequest'teki `text: str`'ı `texts: list[str]` ile değiştirin
|
||||
EmbeddingsResponse'taki `vectors` türünü `list[list[list[float]]]` olarak değiştirin
|
||||
|
||||
### 2. Aşama: İşlemci Güncellemeleri
|
||||
FastEmbed ve Ollama işlemcilerindeki `on_embeddings` imzasını güncelleyin
|
||||
Tam toplu işi tek bir model çağrısında işleyin
|
||||
|
||||
### 3. Aşama: İstemci Güncellemeleri
|
||||
`EmbeddingsClient.embed()`'ı `texts: list[str]`'i kabul edecek şekilde güncelleyin
|
||||
|
||||
### 4. Aşama: Çağıran Güncellemeleri
|
||||
graph_embeddings'i toplu iş varlık bağlamlarını kullanacak şekilde güncelleyin
|
||||
row_embeddings'i toplu iş indeks metinlerini kullanacak şekilde güncelleyin
|
||||
document_embeddings'i yeni şemayı kullanacak şekilde güncelleyin
|
||||
CLI aracını güncelleyin
|
||||
|
||||
### 5. Aşama: API Ağ Geçidi
|
||||
Yeni şema için gömme uç noktasını güncelleyin
|
||||
|
||||
### 6. Aşama: Python SDK
|
||||
`FlowInstance.embeddings()` imzasını güncelleyin
|
||||
`SocketFlowInstance.embeddings()` imzasını güncelleyin
|
||||
|
||||
## Açık Sorular
|
||||
|
||||
**Büyük Toplu İşlerin Akışı**: Çok büyük toplu işler (>100 metin) için sonuçları akış olarak desteklemeli miyiz?
|
||||
**Sağlayıcıya Özel Sınırlar**: Farklı maksimum toplu iş boyutlarına sahip sağlayıcıları nasıl ele almalıyız?
|
||||
**Kısmi Hata İşleme**: Bir toplu işteki bir metin başarısız olursa, tüm toplu işi mi başarısız etmeliyiz yoksa kısmi sonuçları mı döndürmeliyiz?
|
||||
**Belge Gömme Toplu İşleme**: Çoklu Chunk mesajları arasında toplu işlemeyi mi yapmalıyız yoksa her mesaj için ayrı ayrı işlemeyi mi korumalıyız?
|
||||
|
||||
## Referanslar
|
||||
|
||||
[FastEmbed Belgeleri](https://github.com/qdrant/fastembed)
|
||||
[Ollama Gömme API'si](https://github.com/ollama/ollama)
|
||||
[EmbeddingsService Uygulaması](trustgraph-base/trustgraph/base/embeddings_service.py)
|
||||
[GraphRAG Performans Optimizasyonu](graphrag-performance-optimization.md)
|
||||
675
docs/tech-specs/embeddings-batch-processing.zh-cn.md
Normal file
675
docs/tech-specs/embeddings-batch-processing.zh-cn.md
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
---
|
||||
layout: default
|
||||
title: "嵌入式批量处理技术规范"
|
||||
parent: "Chinese (Beta)"
|
||||
---
|
||||
|
||||
# 嵌入式批量处理技术规范
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## 概述
|
||||
|
||||
本规范描述了对嵌入式服务的优化,以支持在单个请求中批量处理多个文本。当前的实现方式一次处理一个文本,而没有利用嵌入式模型在处理批量数据时所能提供的显著性能优势。
|
||||
|
||||
1. **单文本处理效率低下**: 当前实现将单个文本包装在列表中,没有充分利用 FastEmbed 的批量处理能力。
|
||||
2. **每个文本的请求开销**: 每个文本都需要单独的 Pulsar 消息往返。
|
||||
3. **模型推理效率低下**: 嵌入式模型具有固定的批量处理开销;小批量会浪费 GPU/CPU 资源。
|
||||
4. **调用方中的串行处理**: 关键服务循环遍历项目,并一次调用一个嵌入式模型。
|
||||
|
||||
## 目标
|
||||
|
||||
**支持批量 API**: 允许在单个请求中处理多个文本。
|
||||
**向后兼容性**: 保持对单文本请求的支持。
|
||||
**显著的吞吐量提升**: 针对批量操作,目标是实现 5-10 倍的吞吐量提升。
|
||||
**每个文本的降低延迟**: 在嵌入多个文本时,降低平均延迟。
|
||||
**内存效率**: 在不产生过多内存消耗的情况下处理批量数据。
|
||||
**提供商无关性**: 支持 FastEmbed、Ollama 以及其他提供商的批量处理。
|
||||
**调用方迁移**: 更新所有嵌入式模型调用方,以便在有利的情况下使用批量 API。
|
||||
|
||||
## 背景
|
||||
|
||||
### 当前实现 - 嵌入式服务
|
||||
|
||||
位于 `trustgraph-flow/trustgraph/embeddings/fastembed/processor.py` 中的嵌入式实现存在显著的性能低效问题:
|
||||
|
||||
```python
|
||||
# fastembed/processor.py line 56
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
vecs = self.embeddings.embed([text]) # Single text wrapped in list
|
||||
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**问题:**
|
||||
|
||||
1. **批处理大小为 1:** FastEmbed 的 `embed()` 方法针对批量处理进行了优化,但我们总是使用 `[text]` - 批处理大小为 1。
|
||||
|
||||
2. **每个请求的开销:** 每次嵌入请求都涉及:
|
||||
Pulsar 消息序列化/反序列化
|
||||
网络往返延迟
|
||||
模型推理启动开销
|
||||
Python 异步调度开销
|
||||
|
||||
3. **模式限制:** `EmbeddingsRequest` 模式仅支持单个文本:
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
text: str = "" # Single text only
|
||||
```
|
||||
|
||||
### 当前调用者 - 序列化处理
|
||||
|
||||
#### 1. API 网关
|
||||
|
||||
**文件:** `trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
网关通过 HTTP/WebSocket 接收单文本嵌入请求,并将它们转发到嵌入服务。目前没有批量端点。
|
||||
|
||||
```python
|
||||
class EmbeddingsRequestor(ServiceRequestor):
|
||||
# Handles single EmbeddingsRequest -> EmbeddingsResponse
|
||||
request_schema=EmbeddingsRequest, # Single text only
|
||||
response_schema=EmbeddingsResponse,
|
||||
```
|
||||
|
||||
**影响:** 外部客户端(Web应用程序、脚本)必须发出N次HTTP请求才能嵌入N段文本。
|
||||
|
||||
#### 2. 文档嵌入服务
|
||||
|
||||
**文件:** `trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
逐个处理文档块:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
v = msg.value()
|
||||
|
||||
# Single chunk per request
|
||||
resp = await flow("embeddings-request").request(
|
||||
EmbeddingsRequest(text=v.chunk)
|
||||
)
|
||||
vectors = resp.vectors
|
||||
```
|
||||
|
||||
**影响:** 每个文档块都需要单独的嵌入调用。一个包含 100 个块的文档 = 100 个嵌入请求。
|
||||
|
||||
#### 3. 图嵌入服务
|
||||
|
||||
**文件:** `trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
|
||||
循环遍历实体,并逐个嵌入每个实体:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for entity in v.entities:
|
||||
# Serial embedding - one entity at a time
|
||||
vectors = await flow("embeddings-request").embed(
|
||||
text=entity.context
|
||||
)
|
||||
entities.append(EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors,
|
||||
chunk_id=entity.chunk_id,
|
||||
))
|
||||
```
|
||||
|
||||
**影响:** 一个包含 50 个实体的消息意味着 50 个序列化的嵌入请求。这在知识图谱构建过程中是一个主要的瓶颈。
|
||||
|
||||
#### 4. 行嵌入服务
|
||||
|
||||
**文件:** `trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
|
||||
循环遍历唯一的文本,并逐个嵌入每个文本:
|
||||
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
# Serial embedding - one text at a time
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
|
||||
embeddings_list.append(RowIndexEmbedding(
|
||||
index_name=index_name,
|
||||
index_value=index_value,
|
||||
text=text,
|
||||
vectors=vectors
|
||||
))
|
||||
```
|
||||
|
||||
**影响:** 处理包含 100 个唯一索引值的表格 = 100 个序列化嵌入请求。
|
||||
|
||||
#### 5. EmbeddingsClient (基础客户端)
|
||||
|
||||
**文件:** `trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
所有流程处理器使用的客户端仅支持单文本嵌入:
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(self, text, timeout=30):
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(text=text), # Single text
|
||||
timeout=timeout
|
||||
)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
**影响:** 所有使用此客户端的调用者都仅限于执行单文本操作。
|
||||
|
||||
#### 6. 命令行工具
|
||||
|
||||
**文件:** `trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
命令行工具接受单个文本参数:
|
||||
|
||||
```python
|
||||
def query(url, flow_id, text, token=None):
|
||||
result = flow.embeddings(text=text) # Single text
|
||||
vectors = result.get("vectors", [])
|
||||
```
|
||||
|
||||
**影响:** 用户无法通过命令行进行批量嵌入。处理一个文本文件需要 N 次调用。
|
||||
|
||||
#### 7. Python SDK
|
||||
|
||||
Python SDK 提供了两个客户端类,用于与 TrustGraph 服务进行交互。这两个客户端类仅支持单文本嵌入。
|
||||
|
||||
**文件:** `trustgraph-base/trustgraph/api/flow.py`
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, text):
|
||||
"""Get embeddings for a single text"""
|
||||
input = {"text": text}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**文件:** `trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, text: str, **kwargs: Any) -> Dict[str, Any]:
|
||||
"""Get embeddings for a single text via WebSocket"""
|
||||
request = {"text": text}
|
||||
return self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
```
|
||||
|
||||
**影响:** 使用 SDK 的 Python 开发者必须循环遍历文本,并进行 N 次单独的 API 调用。 SDK 用户没有批量嵌入支持。
|
||||
|
||||
### 性能影响
|
||||
|
||||
对于典型的文档导入(1000 个文本块):
|
||||
**当前:** 1000 个单独的请求,1000 次模型推理调用
|
||||
**批量(batch_size=32):** 32 个请求,32 次模型推理调用(减少 96.8%)
|
||||
|
||||
对于图嵌入(包含 50 个实体的消息):
|
||||
**当前:** 50 次序列等待调用,约 5-10 秒
|
||||
**批量:** 1-2 次批量调用,约 0.5-1 秒(提升 5-10 倍)
|
||||
|
||||
FastEmbed 和类似库在批量大小达到硬件限制时,可以实现接近线性的吞吐量扩展(通常每个批次 32-128 个文本)。
|
||||
|
||||
## 技术设计
|
||||
|
||||
### 架构
|
||||
|
||||
嵌入批量处理优化需要修改以下组件:
|
||||
|
||||
#### 1. **模式增强**
|
||||
扩展 `EmbeddingsRequest` 以支持多个文本
|
||||
扩展 `EmbeddingsResponse` 以返回多个向量集合
|
||||
保持与单文本请求的向后兼容性
|
||||
|
||||
模块:`trustgraph-base/trustgraph/schema/services/llm.py`
|
||||
|
||||
#### 2. **基础服务增强**
|
||||
更新 `EmbeddingsService` 以处理批量请求
|
||||
添加批量大小配置
|
||||
实现支持批量请求的处理逻辑
|
||||
|
||||
模块:`trustgraph-base/trustgraph/base/embeddings_service.py`
|
||||
|
||||
#### 3. **提供者处理器更新**
|
||||
更新 FastEmbed 处理器,将整个批次传递给 `embed()`
|
||||
更新 Ollama 处理器,以处理批次(如果支持)
|
||||
为不支持批处理的提供商添加回退的序列化处理
|
||||
|
||||
模块:
|
||||
`trustgraph-flow/trustgraph/embeddings/fastembed/processor.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/ollama/processor.py`
|
||||
|
||||
#### 4. **客户端增强**
|
||||
向 `EmbeddingsClient` 添加批量嵌入方法
|
||||
支持单次和批量 API
|
||||
为大型输入添加自动批量处理
|
||||
|
||||
模块:`trustgraph-base/trustgraph/base/embeddings_client.py`
|
||||
|
||||
#### 5. **调用方更新 - 流处理器**
|
||||
更新 `graph_embeddings` 以批量实体上下文
|
||||
更新 `row_embeddings` 以批量索引文本
|
||||
如果消息批量处理可行,则更新 `document_embeddings`
|
||||
|
||||
模块:
|
||||
`trustgraph-flow/trustgraph/embeddings/graph_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/row_embeddings/embeddings.py`
|
||||
`trustgraph-flow/trustgraph/embeddings/document_embeddings/embeddings.py`
|
||||
|
||||
#### 6. **API 网关增强**
|
||||
添加批量嵌入端点
|
||||
支持请求体中的文本数组
|
||||
|
||||
模块:`trustgraph-flow/trustgraph/gateway/dispatch/embeddings.py`
|
||||
|
||||
#### 7. **CLI 工具增强**
|
||||
添加对多个文本或文件输入的支持
|
||||
添加批量大小参数
|
||||
|
||||
模块:`trustgraph-cli/trustgraph/cli/invoke_embeddings.py`
|
||||
|
||||
#### 8. **Python SDK 增强**
|
||||
向 `FlowInstance` 添加 `embeddings_batch()` 方法
|
||||
向 `SocketFlowInstance` 添加 `embeddings_batch()` 方法
|
||||
为 SDK 用户支持单次和批量 API
|
||||
|
||||
模块:
|
||||
`trustgraph-base/trustgraph/api/flow.py`
|
||||
`trustgraph-base/trustgraph/api/socket_client.py`
|
||||
|
||||
### 数据模型
|
||||
|
||||
#### EmbeddingsRequest
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
用法:
|
||||
单个文本:`EmbeddingsRequest(texts=["hello world"])`
|
||||
批量:`EmbeddingsRequest(texts=["text1", "text2", "text3"])`
|
||||
|
||||
#### EmbeddingsResponse
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
响应结构:
|
||||
`vectors[i]` 包含用于 `texts[i]` 的向量集合。
|
||||
每个向量集合都是 `list[list[float]]` (模型可能为每个文本返回多个向量)。
|
||||
示例:3 个文本 → `vectors` 有 3 个条目,每个条目包含该文本的嵌入向量。
|
||||
|
||||
### API 接口
|
||||
|
||||
#### EmbeddingsClient
|
||||
|
||||
```python
|
||||
class EmbeddingsClient(RequestResponse):
|
||||
async def embed(
|
||||
self,
|
||||
texts: list[str],
|
||||
timeout: float = 300,
|
||||
) -> list[list[list[float]]]:
|
||||
"""
|
||||
Embed one or more texts in a single request.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
timeout: Timeout for the operation
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
resp = await self.request(
|
||||
EmbeddingsRequest(texts=texts),
|
||||
timeout=timeout
|
||||
)
|
||||
if resp.error:
|
||||
raise RuntimeError(resp.error.message)
|
||||
return resp.vectors
|
||||
```
|
||||
|
||||
#### API 网关嵌入式模型端点
|
||||
|
||||
更新后的端点支持单个或批量嵌入式模型:
|
||||
|
||||
```
|
||||
POST /api/v1/embeddings
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"texts": ["text1", "text2", "text3"],
|
||||
"flow_id": "default"
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"vectors": [
|
||||
[[0.1, 0.2, ...]],
|
||||
[[0.3, 0.4, ...]],
|
||||
[[0.5, 0.6, ...]]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 实现细节
|
||||
|
||||
#### 第一阶段:模式更改
|
||||
|
||||
**EmbeddingsRequest:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsRequest:
|
||||
texts: list[str] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**EmbeddingsResponse:**
|
||||
```python
|
||||
@dataclass
|
||||
class EmbeddingsResponse:
|
||||
error: Error | None = None
|
||||
vectors: list[list[list[float]]] = field(default_factory=list)
|
||||
```
|
||||
|
||||
**更新了 EmbeddingsService.on_request:**
|
||||
```python
|
||||
async def on_request(self, msg, consumer, flow):
|
||||
request = msg.value()
|
||||
id = msg.properties()["id"]
|
||||
model = flow("model")
|
||||
|
||||
vectors = await self.on_embeddings(request.texts, model=model)
|
||||
response = EmbeddingsResponse(error=None, vectors=vectors)
|
||||
|
||||
await flow("response").send(response, properties={"id": id})
|
||||
```
|
||||
|
||||
#### 第二阶段:FastEmbed 处理器更新
|
||||
|
||||
**当前(效率低下):**
|
||||
```python
|
||||
async def on_embeddings(self, text, model=None):
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
vecs = self.embeddings.embed([text]) # Batch of 1
|
||||
return [v.tolist() for v in vecs]
|
||||
```
|
||||
|
||||
**更新:**
|
||||
```python
|
||||
async def on_embeddings(self, texts: list[str], model=None):
|
||||
"""Embed texts - processes all texts in single model call"""
|
||||
if not texts:
|
||||
return []
|
||||
|
||||
use_model = model or self.default_model
|
||||
self._load_model(use_model)
|
||||
|
||||
# FastEmbed handles the full batch efficiently
|
||||
all_vecs = list(self.embeddings.embed(texts))
|
||||
|
||||
# Return list of vector sets, one per input text
|
||||
return [[v.tolist()] for v in all_vecs]
|
||||
```
|
||||
|
||||
#### 第三阶段:图嵌入服务更新
|
||||
|
||||
**当前 (序列号):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
entities = []
|
||||
for entity in v.entities:
|
||||
vectors = await flow("embeddings-request").embed(text=entity.context)
|
||||
entities.append(EntityEmbeddings(...))
|
||||
```
|
||||
|
||||
**更新 (批量):**
|
||||
```python
|
||||
async def on_message(self, msg, consumer, flow):
|
||||
# Collect all contexts
|
||||
contexts = [entity.context for entity in v.entities]
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=contexts)
|
||||
|
||||
# Pair results with entities
|
||||
entities = [
|
||||
EntityEmbeddings(
|
||||
entity=entity.entity,
|
||||
vectors=vectors[0], # First vector from the set
|
||||
chunk_id=entity.chunk_id,
|
||||
)
|
||||
for entity, vectors in zip(v.entities, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### 第四阶段:行嵌入服务更新
|
||||
|
||||
**当前 (序列号):**
|
||||
```python
|
||||
for text, (index_name, index_value) in texts_to_embed.items():
|
||||
vectors = await flow("embeddings-request").embed(text=text)
|
||||
embeddings_list.append(RowIndexEmbedding(...))
|
||||
```
|
||||
|
||||
**更新 (批量):**
|
||||
```python
|
||||
# Collect texts and metadata
|
||||
texts = list(texts_to_embed.keys())
|
||||
metadata = list(texts_to_embed.values())
|
||||
|
||||
# Single batch embedding call
|
||||
all_vectors = await flow("embeddings-request").embed(texts=texts)
|
||||
|
||||
# Pair results
|
||||
embeddings_list = [
|
||||
RowIndexEmbedding(
|
||||
index_name=meta[0],
|
||||
index_value=meta[1],
|
||||
text=text,
|
||||
vectors=vectors[0] # First vector from the set
|
||||
)
|
||||
for text, meta, vectors in zip(texts, metadata, all_vectors)
|
||||
]
|
||||
```
|
||||
|
||||
#### 第五阶段:命令行工具增强
|
||||
|
||||
**更新后的命令行界面:**
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(...)
|
||||
|
||||
parser.add_argument(
|
||||
'text',
|
||||
nargs='*', # Zero or more texts
|
||||
help='Text(s) to convert to embedding vectors',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--file',
|
||||
help='File containing texts (one per line)',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--batch-size',
|
||||
type=int,
|
||||
default=32,
|
||||
help='Batch size for processing (default: 32)',
|
||||
)
|
||||
```
|
||||
|
||||
用法:
|
||||
```bash
|
||||
# Single text (existing)
|
||||
tg-invoke-embeddings "hello world"
|
||||
|
||||
# Multiple texts
|
||||
tg-invoke-embeddings "text one" "text two" "text three"
|
||||
|
||||
# From file
|
||||
tg-invoke-embeddings -f texts.txt --batch-size 64
|
||||
```
|
||||
|
||||
#### 第六阶段:Python SDK 增强
|
||||
|
||||
**FlowInstance (HTTP 客户端):**
|
||||
|
||||
```python
|
||||
class FlowInstance:
|
||||
def embeddings(self, texts: list[str]) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
input = {"texts": texts}
|
||||
return self.request("service/embeddings", input)["vectors"]
|
||||
```
|
||||
|
||||
**SocketFlowInstance (WebSocket 客户端):**
|
||||
|
||||
```python
|
||||
class SocketFlowInstance:
|
||||
def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[list[float]]]:
|
||||
"""
|
||||
Get embeddings for one or more texts via WebSocket.
|
||||
|
||||
Args:
|
||||
texts: List of texts to embed
|
||||
|
||||
Returns:
|
||||
List of vector sets, one per input text
|
||||
"""
|
||||
request = {"texts": texts}
|
||||
response = self.client._send_request_sync(
|
||||
"embeddings", self.flow_id, request, False
|
||||
)
|
||||
return response["vectors"]
|
||||
```
|
||||
|
||||
**SDK 使用示例:**
|
||||
|
||||
```python
|
||||
# Single text
|
||||
vectors = flow.embeddings(["hello world"])
|
||||
print(f"Dimensions: {len(vectors[0][0])}")
|
||||
|
||||
# Batch embedding
|
||||
texts = ["text one", "text two", "text three"]
|
||||
all_vectors = flow.embeddings(texts)
|
||||
|
||||
# Process results
|
||||
for text, vecs in zip(texts, all_vectors):
|
||||
print(f"{text}: {len(vecs[0])} dimensions")
|
||||
```
|
||||
|
||||
## 安全注意事项
|
||||
|
||||
**请求大小限制**: 强制执行最大批处理大小,以防止资源耗尽。
|
||||
**超时处理**: 针对批处理大小,适当调整超时时间。
|
||||
**内存限制**: 监控大型批处理的内存使用情况。
|
||||
**输入验证**: 在处理之前,验证批处理中的所有文本。
|
||||
|
||||
## 性能注意事项
|
||||
|
||||
### 预期改进
|
||||
|
||||
**吞吐量**:
|
||||
单个文本: ~10-50 文本/秒 (取决于模型)
|
||||
批处理 (大小 32): ~200-500 文本/秒 (提升 5-10 倍)
|
||||
|
||||
**每个文本的延迟**:
|
||||
单个文本: 每个文本 50-200 毫秒
|
||||
批处理 (大小 32): 每个文本 5-20 毫秒 (摊销值)
|
||||
|
||||
**特定服务的改进**:
|
||||
|
||||
| 服务 | 当前 | 批处理 | 改进 |
|
||||
|---------|---------|---------|-------------|
|
||||
| 图嵌入 (50 个实体) | 5-10 秒 | 0.5-1 秒 | 5-10 倍 |
|
||||
| 行嵌入 (100 个文本) | 10-20 秒 | 1-2 秒 | 5-10 倍 |
|
||||
| 文档导入 (1000 个块) | 100-200 秒 | 10-30 秒 | 5-10 倍 |
|
||||
|
||||
### 配置参数
|
||||
|
||||
```python
|
||||
# Recommended defaults
|
||||
DEFAULT_BATCH_SIZE = 32
|
||||
MAX_BATCH_SIZE = 128
|
||||
BATCH_TIMEOUT_MULTIPLIER = 2.0
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 单元测试
|
||||
单个文本嵌入(向后兼容)
|
||||
空批处理的处理
|
||||
最大批处理大小的强制执行
|
||||
部分批处理失败的错误处理
|
||||
|
||||
### 集成测试
|
||||
通过 Pulsar 进行端到端批处理嵌入
|
||||
图嵌入服务批处理
|
||||
行嵌入服务批处理
|
||||
API 网关批处理端点
|
||||
|
||||
### 性能测试
|
||||
比较单批和批量吞吐量
|
||||
在各种批处理大小下的内存使用情况
|
||||
延迟分布分析
|
||||
|
||||
## 迁移计划
|
||||
|
||||
这是一个破坏性更改版本。所有阶段都一起实施。
|
||||
|
||||
### 第一阶段:Schema 更改
|
||||
将 EmbeddingsRequest 中的 `text: str` 替换为 `texts: list[str]`
|
||||
将 EmbeddingsResponse 中的 `vectors` 类型更改为 `list[list[list[float]]]`
|
||||
|
||||
### 第二阶段:处理器更新
|
||||
更新 FastEmbed 和 Ollama 处理器中的 `on_embeddings` 签名
|
||||
在单个模型调用中处理整个批次
|
||||
|
||||
### 第三阶段:客户端更新
|
||||
更新 `EmbeddingsClient.embed()` 以接受 `texts: list[str]`
|
||||
|
||||
### 第四阶段:调用方更新
|
||||
更新 graph_embeddings 以批处理实体上下文
|
||||
更新 row_embeddings 以批处理索引文本
|
||||
更新 document_embeddings 以使用新的 Schema
|
||||
更新 CLI 工具
|
||||
|
||||
### 第五阶段:API 网关
|
||||
更新用于新 Schema 的嵌入端点
|
||||
|
||||
### 第六阶段:Python SDK
|
||||
更新 `FlowInstance.embeddings()` 签名
|
||||
更新 `SocketFlowInstance.embeddings()` 签名
|
||||
|
||||
## 开放问题
|
||||
|
||||
**大型批处理的流式传输**: 我们是否应该支持对非常大的批处理(>100 个文本)进行流式传输结果?
|
||||
**特定于提供商的限制**: 我们应该如何处理具有不同最大批处理大小的提供商?
|
||||
**部分失败处理**: 如果批处理中的一个文本失败,我们应该使整个批处理失败,还是返回部分结果?
|
||||
**文档嵌入批处理**: 我们应该跨多个 Chunk 消息进行批处理,还是保持每个消息的处理?
|
||||
|
||||
## 参考文献
|
||||
|
||||
[FastEmbed 文档](https://github.com/qdrant/fastembed)
|
||||
[Ollama 嵌入 API](https://github.com/ollama/ollama)
|
||||
[EmbeddingsService 实现](trustgraph-base/trustgraph/base/embeddings_service.py)
|
||||
[GraphRAG 性能优化](graphrag-performance-optimization.md)
|
||||
268
docs/tech-specs/entity-centric-graph.ar.md
Normal file
268
docs/tech-specs/entity-centric-graph.ar.md
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
---
|
||||
layout: default
|
||||
title: "تخزين الرسم البياني المعرفي المرتكز على الكيانات على Cassandra"
|
||||
parent: "Arabic (Beta)"
|
||||
---
|
||||
|
||||
# تخزين الرسم البياني المعرفي المرتكز على الكيانات على Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
يصف هذا المستند نموذج تخزين للرسوم البيانية المعرفية بنمط RDF على Apache Cassandra. يستخدم النموذج نهجًا **مرتكزًا على الكيانات** حيث يعرف كل كيان كل رباعية يشارك فيها والدور الذي يلعبه. هذا يحل محل نهج تبديل SPO متعدد الجداول باستخدام جدولين فقط.
|
||||
|
||||
## الخلفية والدوافع
|
||||
|
||||
### النهج التقليدي
|
||||
|
||||
يتطلب متجر رباعي RDF قياسي على Cassandra جداول متعددة غير طبيعية لتغطية أنماط الاستعلام - عادةً 6 جداول أو أكثر تمثل تبديلات مختلفة للموضوع والمسند والموضوع ومجموعة البيانات (SPOD). يتم كتابة كل رباعية في كل جدول، مما يؤدي إلى تضخيم كبير في عمليات الكتابة، والنفقات التشغيلية، وتعقيد المخطط.
|
||||
|
||||
بالإضافة إلى ذلك، يتطلب تحليل التسميات (جلب أسماء قابلة للقراءة للبشر للكيانات) استعلامات إضافية، وهو أمر مكلف بشكل خاص في حالات استخدام الذكاء الاصطناعي و GraphRAG حيث تعتبر التسميات ضرورية لسياق LLM.
|
||||
|
||||
### الرؤية المرتكزة على الكيانات
|
||||
|
||||
تتضمن كل رباعية `(D, S, P, O)` ما يصل إلى 4 كيانات. من خلال كتابة صف لكل مشاركة للكيان في الرباعية، نضمن أن **أي استعلام يحتوي على عنصر معروف واحد سيضرب مفتاح التقسيم**. يغطي هذا جميع أنماط الاستعلام الـ 16 باستخدام جدول بيانات واحد.
|
||||
|
||||
الفوائد الرئيسية:
|
||||
|
||||
**جدولان** بدلاً من 7 أو أكثر
|
||||
**4 عمليات كتابة لكل رباعية** بدلاً من 6 أو أكثر
|
||||
**تحليل التسميات مجانًا** - يتم تخزين تسميات الكيان مع علاقاته، مما يؤدي بشكل طبيعي إلى تسخين ذاكرة التخزين المؤقت للتطبيق
|
||||
**جميع أنماط الاستعلام الـ 16** يتم تقديمها من خلال قراءات ذات قسم واحد
|
||||
**عمليات أبسط** - جدول بيانات واحد للضبط والضغط والإصلاح
|
||||
|
||||
## المخطط
|
||||
|
||||
### الجدول 1: quads_by_entity
|
||||
|
||||
الجدول الرئيسي للبيانات. يحتوي كل كيان على قسم يحتوي على جميع الرباعيات التي يشارك فيها. تم تسميته ليعكس نمط الاستعلام (البحث حسب الكيان).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_entity (
|
||||
collection text, -- Collection/tenant scope (always specified)
|
||||
entity text, -- The entity this row is about
|
||||
role text, -- 'S', 'P', 'O', 'G' — how this entity participates
|
||||
p text, -- Predicate of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
s text, -- Subject of the quad
|
||||
o text, -- Object of the quad
|
||||
d text, -- Dataset/graph of the quad
|
||||
dtype text, -- XSD datatype (when otype = 'L'), e.g. 'xsd:string'
|
||||
lang text, -- Language tag (when otype = 'L'), e.g. 'en', 'fr'
|
||||
PRIMARY KEY ((collection, entity), role, p, otype, s, o, d, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
**مفتاح التقسيم:** `(collection, entity)` - محدد للنطاق ضمن المجموعة، قسم واحد لكل كيان.
|
||||
|
||||
**المنطق وراء ترتيب أعمدة التجميع:**
|
||||
|
||||
1. **role** - معظم الاستعلامات تبدأ بـ "أين يقع هذا الكيان كموضوع/موضوع؟"
|
||||
2. **p** - المرشح الأكثر شيوعًا بعد ذلك، "أعطني جميع `knows` العلاقات".
|
||||
3. **otype** - يتيح التصفية حسب العلاقات ذات القيم المحددة بواسطة URI مقابل العلاقات ذات القيم الحرفية.
|
||||
4. **s, o, d** - الأعمدة المتبقية لضمان التفرد.
|
||||
5. **dtype, lang** - التمييز بين القيم الحرفية التي لها نفس القيمة ولكن بيانات تعريف نوع مختلفة (على سبيل المثال، `"thing"` مقابل `"thing"@en` مقابل `"thing"^^xsd:string`).
|
||||
|
||||
### الجدول 2: quads_by_collection
|
||||
|
||||
يدعم الاستعلامات والإجراءات الحذف على مستوى المجموعة. يوفر قائمة بجميع الرباعيات التي تنتمي إلى مجموعة. تم تسميته ليعكس نمط الاستعلام (البحث حسب المجموعة).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_collection (
|
||||
collection text,
|
||||
d text, -- Dataset/graph of the quad
|
||||
s text, -- Subject of the quad
|
||||
p text, -- Predicate of the quad
|
||||
o text, -- Object of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
dtype text, -- XSD datatype (when otype = 'L')
|
||||
lang text, -- Language tag (when otype = 'L')
|
||||
PRIMARY KEY (collection, d, s, p, o, otype, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
يتم التجميع بناءً على مجموعة البيانات أولاً، مما يتيح الحذف على مستوى المجموعة أو مستوى مجموعة البيانات. يتم تضمين الأعمدة `otype` و `dtype` و `lang` في مفتاح التجميع للتمييز بين القيم الحرفية التي لها نفس القيمة ولكن بيانات تعريف نوع مختلفة - في RDF، `"thing"` و `"thing"@en` و `"thing"^^xsd:string` هي قيم متميزة دلاليًا.
|
||||
|
||||
## مسار الكتابة
|
||||
|
||||
لكل مجموعة رباعية `(D, S, P, O)` واردة ضمن مجموعة `C`، اكتب **4 صفوف** إلى `quads_by_entity` و **صف واحد** إلى `quads_by_collection`.
|
||||
|
||||
### مثال
|
||||
|
||||
بالنظر إلى المجموعة الرباعية في المجموعة `tenant1`:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: https://example.org/knows
|
||||
Object: https://example.org/Bob
|
||||
```
|
||||
|
||||
اكتب 4 صفوف إلى `quads_by_entity`:
|
||||
|
||||
| collection | entity | role | p | otype | s | o | d |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | G | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Alice | S | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/knows | P | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Bob | O | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
|
||||
اكتب صفًا واحدًا إلى `quads_by_collection`:
|
||||
|
||||
| collection | d | s | p | o | otype | dtype | lang |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | https://example.org/Alice | https://example.org/knows | https://example.org/Bob | U | | |
|
||||
|
||||
### مثال حرفي
|
||||
|
||||
بالنسبة لثلاثية التسمية:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: http://www.w3.org/2000/01/rdf-schema#label
|
||||
Object: "Alice Smith" (lang: en)
|
||||
```
|
||||
|
||||
الرمز `otype` هو `'L'`، و `dtype` هو `'xsd:string'`، و `lang` هو `'en'`. يتم تخزين القيمة الحرفية `"Alice Smith"` في `o`. هناك حاجة إلى 3 صفوف فقط في `quads_by_entity` - لا يتم كتابة أي صف للقيمة الحرفية ككيان، نظرًا لأن القيم الحرفية ليست كيانات قابلة للاستعلام بشكل مستقل.
|
||||
|
||||
## أنماط الاستعلام
|
||||
|
||||
### جميع أنماط DSPO الـ 16
|
||||
|
||||
في الجدول أدناه، تعني عبارة "بادئة مثالية" أن الاستعلام يستخدم بادئة متجاورة لأعمدة التجميع. تعني عبارة "فحص التقسيم + التصفية" أن Cassandra تقرأ جزءًا من التقسيم وتقوم بالتصفية في الذاكرة - لا يزال فعالاً، ولكنه ليس تطابقًا خالصًا للبادئة.
|
||||
|
||||
| # | Known | Lookup entity | Clustering prefix | Efficiency |
|
||||
|---|---|---|---|---|
|
||||
| 1 | D,S,P,O | entity=S, role='S', p=P | تطابق كامل | بادئة مثالية |
|
||||
| 2 | D,S,P,? | entity=S, role='S', p=P | التصفية على D | فحص التقسيم + التصفية |
|
||||
| 3 | D,S,?,O | entity=S, role='S' | التصفية على D، O | فحص التقسيم + التصفية |
|
||||
| 4 | D,?,P,O | entity=O, role='O', p=P | التصفية على D | فحص التقسيم + التصفية |
|
||||
| 5 | ?,S,P,O | entity=S, role='S', p=P | التصفية على O | فحص التقسيم + التصفية |
|
||||
| 6 | D,S,?,? | entity=S, role='S' | التصفية على D | فحص التقسيم + التصفية |
|
||||
| 7 | D,?,P,? | entity=P, role='P' | التصفية على D | فحص التقسيم + التصفية |
|
||||
| 8 | D,?,?,O | entity=O, role='O' | التصفية على D | فحص التقسيم + التصفية |
|
||||
| 9 | ?,S,P,? | entity=S, role='S', p=P | — | **بادئة مثالية** |
|
||||
| 10 | ?,S,?,O | entity=S, role='S' | التصفية على O | فحص التقسيم + التصفية |
|
||||
| 11 | ?,?,P,O | entity=O, role='O', p=P | — | **بادئة مثالية** |
|
||||
| 12 | D,?,?,? | entity=D, role='G' | — | **بادئة مثالية** |
|
||||
| 13 | ?,S,?,? | entity=S, role='S' | — | **بادئة مثالية** |
|
||||
| 14 | ?,?,P,? | entity=P, role='P' | — | **بادئة مثالية** |
|
||||
| 15 | ?,?,?,O | entity=O, role='O' | — | **بادئة مثالية** |
|
||||
| 16 | ?,?,?,? | — | فحص كامل | استكشاف فقط |
|
||||
|
||||
**النتيجة الرئيسية:** 7 من أنماط الـ 15 غير التافهة هي تطابقات مثالية لبادئة التجميع. أما الـ 8 المتبقية فهي قراءات لتقسيم واحد مع تصفية داخل التقسيم. كل استعلام يحتوي على عنصر معروف واحد يطابق مفتاح التقسيم.
|
||||
|
||||
نمط 16 (?,?,?,?) لا يحدث في الممارسة العملية لأنه يتم دائمًا تحديد المجموعة، مما يقلله إلى النمط 12.
|
||||
|
||||
### أمثلة شائعة للاستعلام
|
||||
|
||||
**كل شيء عن كيان:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice';
|
||||
```
|
||||
|
||||
**جميع العلاقات الخارجة لكيان:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S';
|
||||
```
|
||||
|
||||
**شرط محدد لكيان:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows';
|
||||
```
|
||||
|
||||
**تسمية لكيان (بلغة محددة):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'http://www.w3.org/2000/01/rdf-schema#label'
|
||||
AND otype = 'L';
|
||||
```
|
||||
|
||||
ثم قم بالتصفية باستخدام `lang = 'en'` من جانب التطبيق إذا لزم الأمر.
|
||||
|
||||
**فقط العلاقات التي تحمل قيمًا من نوع URI (روابط من كيان إلى كيان):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows' AND otype = 'U';
|
||||
```
|
||||
|
||||
**البحث العكسي - ما الذي يشير إلى هذا الكيان:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Bob'
|
||||
AND role = 'O';
|
||||
```
|
||||
|
||||
## حل التسميات وتدفئة ذاكرة التخزين المؤقت
|
||||
|
||||
أحد أهم مزايا النموذج المرتكز على الكيانات هو أن **يصبح حل التسميات تأثيرًا ثانويًا مجانيًا**.
|
||||
|
||||
في النموذج التقليدي متعدد الجداول، يتطلب استرداد التسميات استعلامات منفصلة: استرداد الثلاثيات، وتحديد معرفات الكيانات في النتائج، ثم استرداد `rdfs:label` لكل منها. هذا النمط N+1 مكلف.
|
||||
|
||||
في النموذج المرتكز على الكيانات، يُرجع الاستعلام عن كيان **جميع** رباعياته - بما في ذلك تسمياته وأنواعه وخصائصه الأخرى. عندما يقوم التطبيق بتخزين نتائج الاستعلام مؤقتًا، يتم تدفئة التسميات مسبقًا قبل أن يطلبها أي شيء.
|
||||
|
||||
يؤكد نظامان للاستخدام على أن هذا يعمل بشكل جيد في الممارسة:
|
||||
|
||||
**الاستعلامات الموجهة للمستخدم**: مجموعات نتائج صغيرة بشكل طبيعي، والتسميات ضرورية. يؤدي قراءة الكيانات إلى تدفئة ذاكرة التخزين المؤقت مسبقًا.
|
||||
**استعلامات الذكاء الاصطناعي/الكمية الكبيرة**: مجموعات نتائج كبيرة مع حدود صارمة. التسميات إما غير ضرورية أو مطلوبة فقط لمجموعة فرعية من الكيانات تم تخزينها بالفعل في ذاكرة التخزين المؤقت.
|
||||
|
||||
يتم تخفيف المخاوف النظرية المتعلقة بحل التسميات لمجموعات نتائج ضخمة (مثل 30000 كيان) بالملاحظة العملية القائلة بأنه لا يمكن لأي مستهلك بشري أو ذكاء اصطناعي معالجة هذا العدد الكبير من التسميات. تضمن حدود الاستعلام على مستوى التطبيق أن يظل ضغط ذاكرة التخزين المؤقت قابلاً للإدارة.
|
||||
|
||||
## التقسيمات العريضة وإعادة التعريف
|
||||
|
||||
يؤدي إعادة التعريف (عبارات على شكل RDF-star حول العبارات) إلى إنشاء كيانات مركزية - على سبيل المثال، مستند مصدر يدعم آلاف الحقائق المستخرجة. يمكن أن يؤدي هذا إلى تقسيمات عريضة.
|
||||
|
||||
عوامل تخفيف:
|
||||
|
||||
**حدود الاستعلام على مستوى التطبيق**: تفرض جميع استعلامات GraphRAG والاستعلامات الموجهة للمستخدم حدودًا صارمة، لذلك لا يتم فحص التقسيمات العريضة بالكامل على مسار القراءة الساخنة.
|
||||
**تتعامل Cassandra بكفاءة مع القراءات الجزئية**: يعد فحص عمود التجميع مع إيقاف مبكر أمرًا سريعًا حتى على التقسيمات الكبيرة.
|
||||
**حذف المجموعة** (العملية الوحيدة التي قد تتجاوز التقسيمات الكاملة) هي عملية خلفية مقبولة.
|
||||
|
||||
## حذف المجموعة
|
||||
|
||||
يتم تشغيله بواسطة استدعاء واجهة برمجة التطبيقات، ويعمل في الخلفية (متسق في النهاية).
|
||||
|
||||
1. اقرأ `quads_by_collection` للمجموعة المستهدفة للحصول على جميع الرباعيات.
|
||||
2. استخرج الكيانات الفريدة من الرباعيات (قيم s و p و o و d).
|
||||
3. لكل كيان فريد، احذف التقسيم من `quads_by_entity`.
|
||||
4. احذف الصفوف من `quads_by_collection`.
|
||||
|
||||
يوفر جدول `quads_by_collection` الفهرس المطلوب لتحديد موقع جميع تقسيمات الكيانات دون فحص كامل للجدول. عمليات حذف التقسيمات فعالة نظرًا لأن `(collection, entity)` هو مفتاح التقسيم.
|
||||
|
||||
## مسار الترحيل من النموذج متعدد الجداول
|
||||
|
||||
يمكن للنموذج المرتكز على الكيانات أن يتعايش مع النموذج متعدد الجداول الحالي أثناء الترحيل:
|
||||
|
||||
1. نشر جداول `quads_by_entity` و `quads_by_collection` جنبًا إلى جنب مع الجداول الحالية.
|
||||
2. الكتابة المزدوجة للرباعيات الجديدة إلى كل من الجداول القديمة والجديدة.
|
||||
3. ملء البيانات الموجودة في الجداول الجديدة.
|
||||
4. ترحيل مسارات القراءة نمط استعلام واحد في كل مرة.
|
||||
5. إلغاء تنشيط الجداول القديمة بمجرد ترحيل جميع عمليات القراءة.
|
||||
|
||||
## ملخص
|
||||
|
||||
| الجانب | تقليدي (6 جداول) | مرتكز على الكيانات (جدولان) |
|
||||
|---|---|---|
|
||||
| الجداول | 7+ | 2 |
|
||||
| عمليات الكتابة لكل رباعية | 6+ | 5 (4 بيانات + 1 بيان) |
|
||||
| حل التسميات | استعلامات منفصلة | مجاني عبر تدفئة ذاكرة التخزين المؤقت |
|
||||
| أنماط الاستعلام | 16 عبر 6 جداول | 16 على جدول واحد |
|
||||
| تعقيد المخطط | مرتفع | منخفض |
|
||||
| النفقات التشغيلية | 6 جداول للتعديل/الإصلاح | جدول بيانات واحد |
|
||||
| دعم إعادة التعريف | تعقيد إضافي | مناسب بشكل طبيعي |
|
||||
| تصفية أنواع الكائنات | غير متوفر | أصلي (عبر التجميع حسب نوع الكائن) |
|
||||
269
docs/tech-specs/entity-centric-graph.es.md
Normal file
269
docs/tech-specs/entity-centric-graph.es.md
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Almacenamiento de Grafos de Conocimiento Centrados en Entidades en Cassandra"
|
||||
parent: "Spanish (Beta)"
|
||||
---
|
||||
|
||||
# Almacenamiento de Grafos de Conocimiento Centrados en Entidades en Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Resumen
|
||||
|
||||
Este documento describe un modelo de almacenamiento para grafos de conocimiento de estilo RDF en Apache Cassandra. El modelo utiliza un enfoque **centrado en entidades** donde cada entidad conoce cada cuadrupla en la que participa y el rol que juega. Esto reemplaza un enfoque tradicional de permutaciones SPO con múltiples tablas con solo dos tablas.
|
||||
|
||||
## Antecedentes y Motivación
|
||||
|
||||
### El Enfoque Tradicional
|
||||
|
||||
Un almacén de cuádruplas RDF estándar en Cassandra requiere múltiples tablas desnormalizadas para cubrir los patrones de consulta, normalmente de 6 o más tablas que representan diferentes permutaciones de Sujeto, Predicado, Objeto y Conjunto de Datos (SPOD). Cada cuadrupla se escribe en cada tabla, lo que resulta en una amplificación de escritura significativa, una sobrecarga operativa y una complejidad del esquema.
|
||||
|
||||
Además, la resolución de etiquetas (obtención de nombres legibles para humanos para las entidades) requiere consultas de ida y vuelta separadas, lo que es particularmente costoso en casos de uso de IA y GraphRAG donde las etiquetas son esenciales para el contexto de los LLM.
|
||||
|
||||
### La Perspectiva Centrada en Entidades
|
||||
|
||||
Cada cuadrupla `(D, S, P, O)` involucra hasta 4 entidades. Al escribir una fila para la participación de cada entidad en la cuadrupla, garantizamos que **cualquier consulta con al menos un elemento conocido golpeará una clave de partición**. Esto cubre los 16 patrones de consulta con una sola tabla de datos.
|
||||
|
||||
Beneficios clave:
|
||||
|
||||
**2 tablas** en lugar de 7+
|
||||
**4 escrituras por cuadrupla** en lugar de 6+
|
||||
**Resolución de etiquetas de forma gratuita**: las etiquetas de una entidad están ubicadas junto con sus relaciones, lo que calienta naturalmente la caché de la aplicación.
|
||||
**Los 16 patrones de consulta** se sirven mediante lecturas de partición única.
|
||||
**Operaciones más simples**: una sola tabla de datos para ajustar, compactar y reparar.
|
||||
|
||||
## Esquema
|
||||
|
||||
### Tabla 1: quads_by_entity
|
||||
|
||||
La tabla de datos principal. Cada entidad tiene una partición que contiene todas las cuádruplas en las que participa. Nombrada para reflejar el patrón de consulta (búsqueda por entidad).
|
||||
Después de la última línea traducida, incluir una línea final que contenga exactamente: [[__END_OF_TRANSLATION__]]
|
||||
```sql
|
||||
CREATE TABLE quads_by_entity (
|
||||
collection text, -- Collection/tenant scope (always specified)
|
||||
entity text, -- The entity this row is about
|
||||
role text, -- 'S', 'P', 'O', 'G' — how this entity participates
|
||||
p text, -- Predicate of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
s text, -- Subject of the quad
|
||||
o text, -- Object of the quad
|
||||
d text, -- Dataset/graph of the quad
|
||||
dtype text, -- XSD datatype (when otype = 'L'), e.g. 'xsd:string'
|
||||
lang text, -- Language tag (when otype = 'L'), e.g. 'en', 'fr'
|
||||
PRIMARY KEY ((collection, entity), role, p, otype, s, o, d, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
**Clave de partición**: `(collection, entity)` — con alcance a la colección, una partición por entidad.
|
||||
|
||||
**Justificación del orden de las columnas de clustering**:
|
||||
|
||||
1. **role** — la mayoría de las consultas comienzan con "dónde está esta entidad como sujeto/objeto".
|
||||
2. **p** — el siguiente filtro más común, "muéstrame todas las relaciones `knows`".
|
||||
3. **otype** — permite filtrar por relaciones con valores URI frente a relaciones con valores literales.
|
||||
4. **s, o, d** — columnas restantes para la unicidad.
|
||||
5. **dtype, lang** — distingue literales con el mismo valor pero con diferentes metadatos de tipo (por ejemplo, `"thing"` vs `"thing"@en` vs `"thing"^^xsd:string`).
|
||||
|
||||
### Tabla 2: quads_by_collection
|
||||
|
||||
Soporta consultas y eliminaciones a nivel de colección. Proporciona un manifiesto de todos los cuads pertenecientes a una colección. Nombrado para reflejar el patrón de consulta (búsqueda por colección).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_collection (
|
||||
collection text,
|
||||
d text, -- Dataset/graph of the quad
|
||||
s text, -- Subject of the quad
|
||||
p text, -- Predicate of the quad
|
||||
o text, -- Object of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
dtype text, -- XSD datatype (when otype = 'L')
|
||||
lang text, -- Language tag (when otype = 'L')
|
||||
PRIMARY KEY (collection, d, s, p, o, otype, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
Agrupados primero por conjunto de datos, lo que permite la eliminación a nivel de colección o de conjunto de datos. Las columnas `otype`, `dtype` y `lang` se incluyen en la clave de agrupación para distinguir literales con el mismo valor pero con diferentes metadatos de tipo; en RDF, `"thing"`, `"thing"@en` y `"thing"^^xsd:string` son valores semánticamente distintos.
|
||||
|
||||
## Ruta de escritura
|
||||
|
||||
Para cada cuadruple entrante `(D, S, P, O)` dentro de una colección `C`, escriba **4 filas** en `quads_by_entity` y **1 fila** en `quads_by_collection`.
|
||||
|
||||
### Ejemplo
|
||||
|
||||
Dado el cuadruple en la colección `tenant1`:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: https://example.org/knows
|
||||
Object: https://example.org/Bob
|
||||
```
|
||||
|
||||
Escriba 4 filas en `quads_by_entity`:
|
||||
|
||||
| collection | entity | role | p | otype | s | o | d |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | G | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Alice | S | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/knows | P | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Bob | O | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
|
||||
Escriba 1 fila en `quads_by_collection`:
|
||||
|
||||
| collection | d | s | p | o | otype | dtype | lang |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | https://example.org/Alice | https://example.org/knows | https://example.org/Bob | U | | |
|
||||
|
||||
### Ejemplo Literal
|
||||
|
||||
Para una tripleta de etiqueta:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: http://www.w3.org/2000/01/rdf-schema#label
|
||||
Object: "Alice Smith" (lang: en)
|
||||
```
|
||||
|
||||
El `otype` es `'L'`, `dtype` es `'xsd:string'`, y `lang` es `'en'`. El valor literal `"Alice Smith"` se almacena en `o`. Solo se necesitan 3 filas en `quads_by_entity`; no se escribe ninguna fila para el literal como entidad, ya que los literales no son entidades consultables de forma independiente.
|
||||
|
||||
## Patrones de consulta
|
||||
|
||||
### Los 16 patrones DSPO
|
||||
|
||||
En la tabla a continuación, "Prefijo perfecto" significa que la consulta utiliza un prefijo contiguo de las columnas de clustering. "Escaneo de partición + filtro" significa que Cassandra lee una porción de una partición y filtra en memoria; es eficiente, pero no es una coincidencia de prefijo pura.
|
||||
|
||||
| # | Conocido | Búsqueda de entidad | Prefijo de clustering | Eficiencia |
|
||||
|---|---|---|---|---|
|
||||
| 1 | D,S,P,O | entidad=S, rol='S', p=P | Coincidencia completa | Prefijo perfecto |
|
||||
| 2 | D,S,P,? | entidad=S, rol='S', p=P | Filtro en D | Escaneo de partición + filtro |
|
||||
| 3 | D,S,?,O | entidad=S, rol='S' | Filtro en D, O | Escaneo de partición + filtro |
|
||||
| 4 | D,?,P,O | entidad=O, rol='O', p=P | Filtro en D | Escaneo de partición + filtro |
|
||||
| 5 | ?,S,P,O | entidad=S, rol='S', p=P | Filtro en O | Escaneo de partición + filtro |
|
||||
| 6 | D,S,?,? | entidad=S, rol='S' | Filtro en D | Escaneo de partición + filtro |
|
||||
| 7 | D,?,P,? | entidad=P, rol='P' | Filtro en D | Escaneo de partición + filtro |
|
||||
| 8 | D,?,?,O | entidad=O, rol='O' | Filtro en D | Escaneo de partición + filtro |
|
||||
| 9 | ?,S,P,? | entidad=S, rol='S', p=P | — | **Prefijo perfecto** |
|
||||
| 10 | ?,S,?,O | entidad=S, rol='S' | Filtro en O | Escaneo de partición + filtro |
|
||||
| 11 | ?,?,P,O | entidad=O, rol='O', p=P | — | **Prefijo perfecto** |
|
||||
| 12 | D,?,?,? | entidad=D, rol='G' | — | **Prefijo perfecto** |
|
||||
| 13 | ?,S,?,? | entidad=S, rol='S' | — | **Prefijo perfecto** |
|
||||
| 14 | ?,?,P,? | entidad=P, rol='P' | — | **Prefijo perfecto** |
|
||||
| 15 | ?,?,?,O | entidad=O, rol='O' | — | **Prefijo perfecto** |
|
||||
| 16 | ?,?,?,? | — | Escaneo completo | Exploración solo |
|
||||
|
||||
**Resultado clave**: 7 de los 15 patrones no triviales son coincidencias perfectas de prefijo de clustering. Los 8 restantes son lecturas de partición única con filtrado dentro de la partición. Cada consulta con al menos un elemento conocido coincide con una clave de partición.
|
||||
|
||||
El patrón 16 (?,?,?,?) no ocurre en la práctica, ya que la colección siempre se especifica, lo que lo reduce al patrón 12.
|
||||
|
||||
### Ejemplos comunes de consultas
|
||||
|
||||
**Todo sobre una entidad:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice';
|
||||
```
|
||||
|
||||
**Todas las relaciones de salida para una entidad:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S';
|
||||
```
|
||||
|
||||
**Predicado específico para una entidad:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows';
|
||||
```
|
||||
|
||||
**Etiqueta para una entidad (idioma específico):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'http://www.w3.org/2000/01/rdf-schema#label'
|
||||
AND otype = 'L';
|
||||
```
|
||||
|
||||
Luego, filtre según la aplicación `lang = 'en'`, si es necesario.
|
||||
|
||||
**Solo relaciones con valores URI (enlaces de entidad a entidad):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows' AND otype = 'U';
|
||||
```
|
||||
|
||||
**Búsqueda inversa: ¿a qué entidades hace referencia esta?**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Bob'
|
||||
AND role = 'O';
|
||||
```
|
||||
|
||||
## Resolución de etiquetas y calentamiento de la caché
|
||||
|
||||
Una de las ventajas más significativas del modelo centrado en entidades es que **la resolución de etiquetas se convierte en un efecto secundario gratuito**.
|
||||
|
||||
En el modelo tradicional de múltiples tablas, recuperar etiquetas requiere consultas separadas: recuperar triples, identificar los URI de las entidades en los resultados y luego recuperar `rdfs:label` para cada uno. Este patrón N+1 es costoso.
|
||||
|
||||
En el modelo centrado en entidades, consultar una entidad devuelve **todos** sus cuads, incluidas sus etiquetas, tipos y otras propiedades. Cuando la aplicación almacena en caché los resultados de las consultas, las etiquetas se precalientan antes de que alguien las solicite.
|
||||
|
||||
Dos regímenes de uso confirman que esto funciona bien en la práctica:
|
||||
|
||||
**Consultas orientadas al usuario**: conjuntos de resultados naturalmente pequeños, las etiquetas son esenciales. Las lecturas de entidades precalientan la caché.
|
||||
**Consultas de IA/masivas**: conjuntos de resultados grandes con límites estrictos. Las etiquetas son innecesarias o se necesitan solo para un subconjunto curado de entidades que ya están en la caché.
|
||||
|
||||
La preocupación teórica de resolver etiquetas para conjuntos de resultados enormes (por ejemplo, 30 000 entidades) se mitiga por la observación práctica de que ningún consumidor humano o de IA procesa útilmente tantas etiquetas. Los límites de consulta a nivel de aplicación garantizan que la presión de la caché siga siendo manejable.
|
||||
|
||||
## Particiones anchas y reificación
|
||||
|
||||
La reificación (declaraciones RDF-star sobre declaraciones) crea entidades de centro, por ejemplo, un documento de origen que admite miles de hechos extraídos. Esto puede producir particiones anchas.
|
||||
|
||||
Factores atenuantes:
|
||||
|
||||
**Límites de consulta a nivel de aplicación**: todas las consultas de GraphRAG y orientadas al usuario imponen límites estrictos, por lo que las particiones anchas nunca se escanean completamente en la ruta de lectura activa.
|
||||
**Cassandra maneja las lecturas parciales de manera eficiente**: un escaneo de columna de agrupación con una parada temprana es rápido incluso en particiones grandes.
|
||||
**Eliminación de colecciones** (la única operación que podría recorrer particiones completas) es un proceso de segundo plano aceptable.
|
||||
|
||||
## Eliminación de colecciones
|
||||
|
||||
Se activa mediante una llamada a la API, se ejecuta en segundo plano (consistencia eventual).
|
||||
|
||||
1. Leer `quads_by_collection` para la colección de destino para obtener todos los cuads.
|
||||
2. Extraer entidades únicas de los cuads (valores s, p, o, d).
|
||||
3. Para cada entidad única, eliminar la partición de `quads_by_entity`.
|
||||
4. Eliminar las filas de `quads_by_collection`.
|
||||
|
||||
La tabla `quads_by_collection` proporciona el índice necesario para localizar todas las particiones de entidades sin un escaneo completo de la tabla. Las eliminaciones a nivel de partición son eficientes porque `(collection, entity)` es la clave de partición.
|
||||
|
||||
## Ruta de migración desde el modelo de múltiples tablas
|
||||
|
||||
El modelo centrado en entidades puede coexistir con el modelo de múltiples tablas existente durante la migración:
|
||||
|
||||
1. Implementar las tablas `quads_by_entity` y `quads_by_collection` junto con las tablas existentes.
|
||||
2. Escribir duplicados nuevos cuads tanto en las tablas antiguas como en las nuevas.
|
||||
3. Rellenar los datos existentes en las nuevas tablas.
|
||||
4. Migrar las rutas de consulta un patrón a la vez.
|
||||
5. Desactivar las tablas antiguas una vez que todas las lecturas se hayan migrado.
|
||||
|
||||
## Resumen
|
||||
|
||||
| Aspecto | Tradicional (6 tablas) | Centrado en entidades (2 tablas) |
|
||||
|---|---|---|
|
||||
| Tablas | 7+ | 2 |
|
||||
| Escrituras por quad | 6+ | 5 (4 datos + 1 manifiesto) |
|
||||
| Resolución de etiquetas | Viajes separados | Gratuito a través del calentamiento de la caché |
|
||||
| Patrones de consulta | 16 en 6 tablas | 16 en 1 tabla |
|
||||
| Complejidad del esquema | Alto | Bajo |
|
||||
| Sobrecarga operativa | 6 tablas para ajustar/reparar | 1 tabla de datos |
|
||||
| Soporte de reificación | Complejidad adicional | Ajuste natural |
|
||||
| Filtrado de tipo de objeto | No disponible | Nativo (a través de la agrupación de otype) |
|
||||
Después de la última línea traducida, incluir una línea final que contenga exactamente: [[__END_OF_TRANSLATION__]]
|
||||
269
docs/tech-specs/entity-centric-graph.he.md
Normal file
269
docs/tech-specs/entity-centric-graph.he.md
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
---
|
||||
layout: default
|
||||
title: "אחסון גרף ידע ממוקד ישויות ב-Cassandra"
|
||||
parent: "Hebrew (Beta)"
|
||||
---
|
||||
|
||||
# אחסון גרף ידע ממוקד ישויות ב-Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## סקירה כללית
|
||||
|
||||
מסמך זה מתאר מודל אחסון עבור גרפי ידע מסוג RDF ב-Apache Cassandra. המודל משתמש בגישה **ממוקדת ישויות**, כאשר כל ישות יודעת כל רביעיות (quads) בהן היא משתתפת והתפקיד שלה. זה מחליף גישה מסורתית של מספר טבלאות המייצגות את כל הפרמוטציות של Subject, Predicate, Object ו-Dataset (SPOD) עם שתי טבלאות בלבד.
|
||||
|
||||
## רקע ומניעים
|
||||
|
||||
### הגישה המסורתית
|
||||
|
||||
חנות רביעיות RDF סטנדרטית ב-Cassandra דורשת מספר טבלאות לא מנורמלות כדי לכסות דפוסי שאילתות - בדרך כלל 6 טבלאות או יותר המייצגות את הפרמוטציות השונות של Subject, Predicate, Object ו-Dataset (SPOD). כל רביעייה נכתבת לכל טבלה, מה שגורם להגדלת כתיבה משמעותית, תקורה תפעולית ומורכבות סכימה.
|
||||
|
||||
בנוסף, פתרון תוויות (שליפת שמות קריאים לבני אדם עבור ישויות) דורש שאילתות נפרדות, דבר שיכול להיות יקר במיוחד במקרי שימוש של AI ו-GraphRAG, שבהם תוויות חיוניות להקשר של מודלי שפה גדולים (LLM).
|
||||
|
||||
### התובנה הממוקדת בישות
|
||||
|
||||
כל רביעייה `(D, S, P, O)` כוללת עד 4 ישויות. על ידי כתיבת שורה עבור כל השתתפות של ישות ברביעייה, אנו מבטיחים ש-**כל שאילתה עם לפחות רכיב אחד ידוע תפגע במפתח מחיצה**. זה מכסה את כל 16 דפוסי השאילתות עם טבלת נתונים אחת.
|
||||
|
||||
יתרונות עיקריים:
|
||||
|
||||
**2 טבלאות** במקום 7+
|
||||
**4 כתיבות לרביעייה** במקום 6+
|
||||
**פתרון תוויות בחינם** - התוויות של ישות נמצאות יחד עם הקשרים שלה, מה שמחמם באופן טבעי את מטמון האפליקציה.
|
||||
**כל 16 דפוסי השאילתות** נגישים באמצעות קריאות מחיצה יחידה.
|
||||
**פעולות פשוטות יותר** - טבלת נתונים אחת לכוונן, לדחוס ולתקן.
|
||||
|
||||
## סכימה
|
||||
|
||||
### טבלה 1: quads_by_entity
|
||||
|
||||
טבלת הנתונים העיקרית. לכל ישות יש מחיצה המכילה את כל הרביעיות בהן היא משתתפת. נקראה כך כדי לשקף את דפוס השאילתה (חיפוש לפי ישות).
|
||||
פלט חוזה (יש לעקוב אחר הפורמט המדויק).
|
||||
```sql
|
||||
CREATE TABLE quads_by_entity (
|
||||
collection text, -- Collection/tenant scope (always specified)
|
||||
entity text, -- The entity this row is about
|
||||
role text, -- 'S', 'P', 'O', 'G' — how this entity participates
|
||||
p text, -- Predicate of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
s text, -- Subject of the quad
|
||||
o text, -- Object of the quad
|
||||
d text, -- Dataset/graph of the quad
|
||||
dtype text, -- XSD datatype (when otype = 'L'), e.g. 'xsd:string'
|
||||
lang text, -- Language tag (when otype = 'L'), e.g. 'en', 'fr'
|
||||
PRIMARY KEY ((collection, entity), role, p, otype, s, o, d, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
**מפתח מחיצה**: `(collection, entity)` — מוגבל לאוסף, מחיצה אחת לכל ישות.
|
||||
|
||||
**ההצדקה עבור סדר עמודי הצבירה**:
|
||||
|
||||
1. **role** — רוב השאילתות מתחילות ב"היכן נמצאת ישות זו כנושא/אובייקט"
|
||||
2. **p** — מסנן נפוץ נוסף, "תן לי את כל `knows` הקשרים"
|
||||
3. **otype** — מאפשר סינון לפי קשרים בעלי ערך URI לעומת קשרים בעלי ערך מילולי
|
||||
4. **s, o, d** — עמודות שנותרו לשם ייחודיות
|
||||
5. **dtype, lang** — מבדילים בין מילולים בעלי אותו ערך אך מטא-נתונים שונים (לדוגמה, `"thing"` לעומת `"thing"@en` לעומת `"thing"^^xsd:string`)
|
||||
|
||||
### טבלה 2: quads_by_collection
|
||||
|
||||
תומך בשאילתות ובמחיקות ברמת האוסף. מספק תצוגה של כל ה-quads השייכים לאוסף. נקרא כך כדי לשקף את דפוס השאילתה (חיפוש לפי אוסף).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_collection (
|
||||
collection text,
|
||||
d text, -- Dataset/graph of the quad
|
||||
s text, -- Subject of the quad
|
||||
p text, -- Predicate of the quad
|
||||
o text, -- Object of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
dtype text, -- XSD datatype (when otype = 'L')
|
||||
lang text, -- Language tag (when otype = 'L')
|
||||
PRIMARY KEY (collection, d, s, p, o, otype, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
מאוגדים לפי קבוצת נתונים תחילה, מה שמאפשר מחיקה ברמת אוסף או ברמת קבוצת נתונים. העמודות `otype`, `dtype` ו-`lang` כלולות במפתח האריגה כדי להבחין בין ערכים המילוליים עם אותו ערך אך עם מטא-נתונים מסוג שונים - ב-RDF, `"thing"`, `"thing"@en` ו-`"thing"^^xsd:string` הם ערכים שונים מבחינה סמנטית.
|
||||
|
||||
## נתיב כתיבה
|
||||
|
||||
עבור כל רביעייה נכנסת `(D, S, P, O)` בתוך אוסף `C`, כתבו **4 שורות** ל-`quads_by_entity` ו-**שורה אחת** ל-`quads_by_collection`.
|
||||
|
||||
### דוגמה
|
||||
|
||||
בהינתן הרביעייה באוסף `tenant1`:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: https://example.org/knows
|
||||
Object: https://example.org/Bob
|
||||
```
|
||||
|
||||
כתוב 4 שורות ל-`quads_by_entity`:
|
||||
|
||||
| collection | entity | role | p | otype | s | o | d |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | G | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Alice | S | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/knows | P | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Bob | O | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
|
||||
כתוב שורה אחת ל-`quads_by_collection`:
|
||||
|
||||
| collection | d | s | p | o | otype | dtype | lang |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | https://example.org/Alice | https://example.org/knows | https://example.org/Bob | U | | |
|
||||
|
||||
### דוגמה מילולית
|
||||
|
||||
עבור משולש תווית:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: http://www.w3.org/2000/01/rdf-schema#label
|
||||
Object: "Alice Smith" (lang: en)
|
||||
```
|
||||
|
||||
הקוד `otype` הוא `'L'`, `dtype` הוא `'xsd:string'`, ו-`lang` הוא `'en'`. הערך המילולי `"Alice Smith"` מאוחסן ב-`o`. נדרשות רק 3 שורות ב-`quads_by_entity` - שורה אינה נכתבת עבור הערך המילולי כישות, מכיוון שערכים מילוליים אינם ישויות שאפשר לשאול אותן באופן עצמאי.
|
||||
|
||||
## תבניות שאילתה
|
||||
|
||||
### כל 16 תבניות DSPO
|
||||
|
||||
בטבלה למטה, "קידומת מושלמת" פירושה שהשאילתה משתמשת בקידומת רציפה של עמודי הקיבוץ. "סריקת מחיצה + סינון" פירושה ש-Cassandra קוראת חלק ממחיצה ומסננת בזיכרון - יעיל, אבל לא התאמה מדויקת לקידומת.
|
||||
|
||||
| # | ידוע | ישות | קידומת קיבוץ | יעילות |
|
||||
|---|---|---|---|---|
|
||||
| 1 | D,S,P,O | entity=S, role='S', p=P | התאמה מלאה | קידומת מושלמת |
|
||||
| 2 | D,S,P,? | entity=S, role='S', p=P | סינון על D | סריקת מחיצה + סינון |
|
||||
| 3 | D,S,?,O | entity=S, role='S' | סינון על D, O | סריקת מחיצה + סינון |
|
||||
| 4 | D,?,P,O | entity=O, role='O', p=P | סינון על D | סריקת מחיצה + סינון |
|
||||
| 5 | ?,S,P,O | entity=S, role='S', p=P | סינון על O | סריקת מחיצה + סינון |
|
||||
| 6 | D,S,?,? | entity=S, role='S' | סינון על D | סריקת מחיצה + סינון |
|
||||
| 7 | D,?,P,? | entity=P, role='P' | סינון על D | סריקת מחיצה + סינון |
|
||||
| 8 | D,?,?,O | entity=O, role='O' | סינון על D | סריקת מחיצה + סינון |
|
||||
| 9 | ?,S,P,? | entity=S, role='S', p=P | — | **קידומת מושלמת** |
|
||||
| 10 | ?,S,?,O | entity=S, role='S' | סינון על O | סריקת מחיצה + סינון |
|
||||
| 11 | ?,?,P,O | entity=O, role='O', p=P | — | **קידומת מושלמת** |
|
||||
| 12 | D,?,?,? | entity=D, role='G' | — | **קידומת מושלמת** |
|
||||
| 13 | ?,S,?,? | entity=S, role='S' | — | **קידומת מושלמת** |
|
||||
| 14 | ?,?,P,? | entity=P, role='P' | — | **קידומת מושלמת** |
|
||||
| 15 | ?,?,?,O | entity=O, role='O' | — | **קידומת מושלמת** |
|
||||
| 16 | ?,?,?,? | — | סריקה מלאה | חקירה בלבד |
|
||||
|
||||
**תוצאה עיקרית**: 7 מתוך 15 התבניות הלא טריוויאליות הן התאמות מושלמות לקידומת קיבוץ. שמונה הנותרות הן קריאות מחיצה בודדות עם סינון בתוך המחיצה. כל שאילתה עם לפחות רכיב ידוע פוגעת במפתח המחיצה.
|
||||
|
||||
התבנית 16 (?,?,?,?) אינה מתרחשת בפועל מכיוון שאוסף תמיד מצוין, מה שמצמצם אותה לתבנית 12.
|
||||
|
||||
### דוגמאות נפוצות לשאילתות
|
||||
|
||||
**כל דבר על ישות:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice';
|
||||
```
|
||||
|
||||
**כל הקשרים יוצאים עבור ישות:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S';
|
||||
```
|
||||
|
||||
**תכונה ספציפית עבור ישות:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows';
|
||||
```
|
||||
|
||||
**תווית עבור ישות (שפה ספציפית):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'http://www.w3.org/2000/01/rdf-schema#label'
|
||||
AND otype = 'L';
|
||||
```
|
||||
|
||||
לאחר מכן, במידת הצורך, סננו באמצעות `lang = 'en'` בצד האפליקציה.
|
||||
|
||||
**רק קשרים בעלי ערך URI (קישורים בין ישויות לישויות):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows' AND otype = 'U';
|
||||
```
|
||||
|
||||
**חיפוש הפוך — מה מצביע על ישות זו:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Bob'
|
||||
AND role = 'O';
|
||||
```
|
||||
|
||||
## פתרון תוויות וחימום מטמון
|
||||
|
||||
אחד היתרונות המשמעותיים ביותר של מודל המרכז את הישות הוא ש**פתרון תוויות הופך לתופעת לוואי חופשית**.
|
||||
|
||||
במודל הרב-טבלאי המסורתי, שליפת תוויות דורשת שאילתות נפרדות: יש לשלוף משולשות, לזהות את כתובות ה-URI של הישויות בתוצאות, ולאחר מכן לשלוף `rdfs:label` עבור כל אחת. דפוס N+1 זה יקר.
|
||||
|
||||
במודל המרכז את הישות, שאילתה של ישות מחזירה את כל ה-quads שלה - כולל התוויות, הסוגים ותכונות אחרות. כאשר האפליקציה שומרת תוצאות שאילתה במטמון, התוויות מחוממות מראש לפני שמישהו מבקש אותן.
|
||||
|
||||
שני מצבי שימוש מאשרים שזה עובד היטב בפועל:
|
||||
|
||||
**שאילתות המיועדות למשתמשים**: קבוצות תוצאות קטנות באופן טבעי, תוויות חיוניות. קריאות לישות מחממות את המטמון מראש.
|
||||
**שאילתות AI/מערכיות**: קבוצות תוצאות גדולות עם מגבלות קשות. תוויות או שאינן נחוצות או נדרשות רק עבור תת-קבוצה מבוקרת של ישויות שכבר נמצאות במטמון.
|
||||
|
||||
החשש התיאורטי של פתרון תוויות עבור קבוצות תוצאות גדולות (לדוגמה, 30,000 ישויות) מופחת על ידי התצפית המעשית שאף צרכן אנושי או AI לא מעבד שימושית כמות כזו של תוויות. מגבלות שאילתה ברמת האפליקציה מבטיחות שלחץ המטמון נשאר ניתן לניהול.
|
||||
|
||||
## מחיצות רחבות ומימוש
|
||||
|
||||
מימוש (הצהרות מסוג RDF-star על הצהרות) יוצר ישויות מרכזיות - לדוגמה, מסמך מקור התומך באלפי עובדות שחולצו. זה יכול ליצור מחיצות רחבות.
|
||||
|
||||
גורמים מקלים:
|
||||
|
||||
**מגבלות שאילתה ברמת האפליקציה**: כל שאילתות GraphRAG ושאילתות המיועדות למשתמשים מאכפות מגבלות קשות, כך שמחיצות רחבות לעולם אינן נסרקות במלואן בנתיב הקריאה החמה
|
||||
**Cassandra מטפלת בקריאות חלקיות בצורה יעילה**: סריקת עמודת קיבוץ עם עצירה מוקדמת היא מהירה גם על מחיצות גדולות
|
||||
**מחיקת אוסף** (הפעולה היחידה שעשויה לעבור על מחיצות מלאות) היא תהליך רקע מקובל
|
||||
|
||||
## מחיקת אוסף
|
||||
|
||||
מופעלת על ידי קריאת API, רצה ברקע (עקביות בסופו של דבר).
|
||||
|
||||
1. קרא `quads_by_collection` עבור האוסף המיועד כדי לקבל את כל ה-quads
|
||||
2. חלץ ישויות ייחודיות מה-quads (ערכי s, p, o, d)
|
||||
3. עבור כל ישות ייחודית, מחק את המחיצה מ-`quads_by_entity`
|
||||
4. מחק את השורות מ-`quads_by_collection`
|
||||
|
||||
הטבלה `quads_by_collection` מספקת את האינדקס הדרוש כדי לאתר את כל מחיצות הישויות מבלי לסרוק את הטבלה כולה. מחיקות ברמת המחיצה יעילות מכיוון ש-`(collection, entity)` הוא מפתח המחיצה.
|
||||
|
||||
## נתיב מעבר ממודל רב-טבלאי
|
||||
|
||||
מודל המרכז את הישות יכול לדור בכפיפות למודל הרב-טבלאי הקיים במהלך המעבר:
|
||||
|
||||
1. פרוס את הטבלאות `quads_by_entity` ו-`quads_by_collection` לצד הטבלאות הקיימות
|
||||
2. כתוב כפול quads חדשים גם לטבלאות הישנות וגם לטבלאות החדשות
|
||||
3. מלא נתונים קיימים לתוך הטבלאות החדשות
|
||||
4. העבר נתיבי קריאה דפוס שאילתה בכל פעם
|
||||
5. הפסק את פעולת הטבלאות הישנות לאחר שכל הקריאות עברו
|
||||
|
||||
## סיכום
|
||||
|
||||
| היבט | מסורתי (6 טבלאות) | מרכז ישות (2 טבלאות) |
|
||||
|---|---|---|
|
||||
| טבלאות | 7+ | 2 |
|
||||
| כתיבות לכל quad | 6+ | 5 (4 נתונים + 1 מניפסט) |
|
||||
| פתרון תוויות | מעברי נסיעה נפרדים | חימום מטמון חופשי |
|
||||
| דפוסי שאילתה | 16 על פני 6 טבלאות | 16 על טבלה אחת |
|
||||
| מורכבות סכימה | גבוהה | נמוכה |
|
||||
| תקורה תפעולית | 6 טבלאות לכיול/תיקון | טבלת נתונים אחת |
|
||||
| תמיכה במימוש | מורכבות נוספת | התאמה טבעית |
|
||||
| סינון סוגי אובייקטים | לא זמין | ילידי (דרך קיבוץ otype) |
|
||||
פלט חוזה (יש לעקוב בדיוק אחר הפורמט).
|
||||
268
docs/tech-specs/entity-centric-graph.hi.md
Normal file
268
docs/tech-specs/entity-centric-graph.hi.md
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
---
|
||||
layout: default
|
||||
title: "एंटिटी-सेंट्रिक नॉलेज ग्राफ स्टोरेज ऑन कैसेंड्रा"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# एंटिटी-सेंट्रिक नॉलेज ग्राफ स्टोरेज ऑन कैसेंड्रा
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## अवलोकन
|
||||
|
||||
यह दस्तावेज़ अपाचे कैसेंड्रा पर आरडीएफ-शैली नॉलेज ग्राफ के लिए एक स्टोरेज मॉडल का वर्णन करता है। यह मॉडल एक **एंटिटी-सेंट्रिक** दृष्टिकोण का उपयोग करता है, जिसमें प्रत्येक एंटिटी उन सभी क्वाड के बारे में जानती है जिनमें वह भाग लेता है और वह जो भूमिका निभाता है। यह पारंपरिक मल्टी-टेबल एस.पी.ओ. क्रमपरिवर्तन दृष्टिकोण को केवल दो तालिकाओं से बदल देता है।
|
||||
|
||||
## पृष्ठभूमि और प्रेरणा
|
||||
|
||||
### पारंपरिक दृष्टिकोण
|
||||
|
||||
कैसेंड्रा पर एक मानक आरडीएफ क्वाड स्टोर को क्वेरी पैटर्न को कवर करने के लिए कई डीनॉर्मलाइज़्ड तालिकाओं की आवश्यकता होती है - आमतौर पर 6 या अधिक टेबल जो विषय, विधेय, वस्तु और डेटासेट (एसपीओडी) के विभिन्न क्रमपरिवर्तनों का प्रतिनिधित्व करते हैं। प्रत्येक क्वाड को प्रत्येक तालिका में लिखा जाता है, जिसके परिणामस्वरूप महत्वपूर्ण राइट एम्प्लीफिकेशन, परिचालन ओवरहेड और स्कीमा जटिलता होती है।
|
||||
|
||||
इसके अतिरिक्त, लेबल रिज़ॉल्यूशन (एंटिटीज के लिए मानव-पठनीय नामों को प्राप्त करना) के लिए अलग राउंड-ट्रिप क्वेरी की आवश्यकता होती है, जो एआई और ग्राफआरएजी उपयोग के मामलों में विशेष रूप से महंगी होती है, जहां एलएलएम संदर्भ के लिए लेबल आवश्यक हैं।
|
||||
|
||||
### एंटिटी-सेंट्रिक अंतर्दृष्टि
|
||||
|
||||
प्रत्येक क्वाड `(D, S, P, O)` में अधिकतम 4 एंटिटीज शामिल होती हैं। प्रत्येक एंटिटी की क्वाड में भागीदारी के लिए एक पंक्ति लिखकर, हम यह गारंटी देते हैं कि **किसी भी क्वेरी में कम से कम एक ज्ञात तत्व होगा, जो एक विभाजन कुंजी पर हिट करेगा।** यह एकल डेटा तालिका के साथ सभी 16 क्वेरी पैटर्न को कवर करता है।
|
||||
|
||||
मुख्य लाभ:
|
||||
|
||||
**2 टेबल** 7+ तालिकाओं के बजाय
|
||||
**प्रति क्वाड 4 राइट** 6+ राइट के बजाय
|
||||
**लेबल रिज़ॉल्यूशन मुफ्त में** - एक एंटिटी के लेबल उसके संबंधों के साथ स्थित होते हैं, जो स्वाभाविक रूप से एप्लिकेशन कैश को गर्म करते हैं
|
||||
**सभी 16 क्वेरी पैटर्न** सिंगल-पार्टिशन रीड द्वारा परोसे जाते हैं
|
||||
**सरल संचालन** - ट्यून करने, कंपैक्ट करने और रिपेयर करने के लिए एक डेटा टेबल
|
||||
|
||||
## स्कीमा
|
||||
|
||||
### टेबल 1: quads_by_entity
|
||||
|
||||
प्राथमिक डेटा तालिका। प्रत्येक एंटिटी में एक विभाजन होता है जिसमें वह सभी क्वाड शामिल होते हैं जिनमें वह भाग लेता है। क्वेरी पैटर्न (एंटिटी द्वारा लुकअप) को दर्शाने के लिए नामित।
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_entity (
|
||||
collection text, -- Collection/tenant scope (always specified)
|
||||
entity text, -- The entity this row is about
|
||||
role text, -- 'S', 'P', 'O', 'G' — how this entity participates
|
||||
p text, -- Predicate of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
s text, -- Subject of the quad
|
||||
o text, -- Object of the quad
|
||||
d text, -- Dataset/graph of the quad
|
||||
dtype text, -- XSD datatype (when otype = 'L'), e.g. 'xsd:string'
|
||||
lang text, -- Language tag (when otype = 'L'), e.g. 'en', 'fr'
|
||||
PRIMARY KEY ((collection, entity), role, p, otype, s, o, d, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
**विभाजन कुंजी (पार्टिशन की):** `(collection, entity)` — संग्रह के लिए निर्धारित, प्रत्येक इकाई के लिए एक विभाजन।
|
||||
|
||||
**क्लस्टरिंग कॉलम क्रम का तर्क:**
|
||||
|
||||
1. **भूमिका (role):** अधिकांश क्वेरी "यह इकाई विषय/वस्तु है" से शुरू होती हैं।
|
||||
2. **p:** अगला सबसे आम फ़िल्टर, "मुझे सभी `knows` संबंध दिखाएं"।
|
||||
3. **otype:** URI-मान वाले बनाम शाब्दिक-मान वाले संबंधों के आधार पर फ़िल्टर करने में सक्षम बनाता है।
|
||||
4. **s, o, d:** विशिष्टता के लिए शेष कॉलम।
|
||||
5. **dtype, lang:** समान मान वाले लेकिन अलग-अलग प्रकार के मेटाडेटा वाले शाब्दिकों को अलग करने के लिए (उदाहरण के लिए, `"thing"` बनाम `"thing"@en` बनाम `"thing"^^xsd:string`)।
|
||||
|
||||
### तालिका 2: quads_by_collection
|
||||
|
||||
संग्रह-स्तरीय क्वेरी और हटाने का समर्थन करता है। यह एक संग्रह से संबंधित सभी क्वाड का एक विवरण प्रदान करता है। इसे उस क्वेरी पैटर्न को दर्शाने के लिए नामित किया गया है (संग्रह द्वारा खोज)।
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_collection (
|
||||
collection text,
|
||||
d text, -- Dataset/graph of the quad
|
||||
s text, -- Subject of the quad
|
||||
p text, -- Predicate of the quad
|
||||
o text, -- Object of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
dtype text, -- XSD datatype (when otype = 'L')
|
||||
lang text, -- Language tag (when otype = 'L')
|
||||
PRIMARY KEY (collection, d, s, p, o, otype, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
सबसे पहले डेटासेट के आधार पर समूहीकृत किया जाता है, जिससे संग्रह या डेटासेट स्तर पर हटाने की सुविधा मिलती है। `otype`, `dtype`, और `lang` कॉलम को समूहीकरण कुंजी में शामिल किया गया है ताकि समान मान वाले लिटरल को अलग किया जा सके, लेकिन अलग-अलग प्रकार के मेटाडेटा के साथ - RDF में, `"thing"`, `"thing"@en`, और `"thing"^^xsd:string` अर्थपूर्ण रूप से भिन्न मान हैं।
|
||||
|
||||
## लेखन पथ
|
||||
|
||||
प्रत्येक आने वाले क्वाड `(D, S, P, O)` के लिए, जो संग्रह `C` के भीतर है, `quads_by_entity` में **4 पंक्तियाँ** और `quads_by_collection` में **1 पंक्ति** लिखें।
|
||||
|
||||
### उदाहरण
|
||||
|
||||
संग्रह `tenant1` में क्वाड दिया गया है:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: https://example.org/knows
|
||||
Object: https://example.org/Bob
|
||||
```
|
||||
|
||||
`quads_by_entity` में 4 पंक्तियाँ लिखें:
|
||||
|
||||
| संग्रह | इकाई | भूमिका | p | otype | s | o | d |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | G | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Alice | S | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/knows | P | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Bob | O | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
|
||||
`quads_by_collection` में 1 पंक्ति लिखें:
|
||||
|
||||
| संग्रह | d | s | p | o | otype | dtype | lang |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | https://example.org/Alice | https://example.org/knows | https://example.org/Bob | U | | |
|
||||
|
||||
### शाब्दिक उदाहरण
|
||||
|
||||
एक लेबल ट्रिपल के लिए:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: http://www.w3.org/2000/01/rdf-schema#label
|
||||
Object: "Alice Smith" (lang: en)
|
||||
```
|
||||
|
||||
`otype` का मान `'L'` है, `dtype` का मान `'xsd:string'` है, और `lang` का मान `'en'` है। शाब्दिक मान `"Alice Smith"` को `o` में संग्रहीत किया जाता है। `quads_by_entity` में केवल 3 पंक्तियों की आवश्यकता होती है - शाब्दिक को इकाई के रूप में लिखने के लिए कोई पंक्ति नहीं लिखी जाती है, क्योंकि शाब्दिक स्वतंत्र रूप से क्वेरी करने योग्य इकाइयाँ नहीं हैं।
|
||||
|
||||
## क्वेरी पैटर्न
|
||||
|
||||
### सभी 16 डीएसपीओ पैटर्न
|
||||
|
||||
नीचे दी गई तालिका में, "परिपूर्ण उपसर्ग" का अर्थ है कि क्वेरी क्लस्टरिंग कॉलम के एक निरंतर उपसर्ग का उपयोग करती है। "विभाजन स्कैन + फ़िल्टर" का अर्थ है कि कैसेंड्रा एक विभाजन के एक स्लाइस को पढ़ता है और मेमोरी में फ़िल्टर करता है - यह कुशल है, लेकिन यह एक शुद्ध उपसर्ग मिलान नहीं है।
|
||||
|
||||
| # | ज्ञात | लुकअप इकाई | क्लस्टरिंग उपसर्ग | दक्षता |
|
||||
|---|---|---|---|---|
|
||||
| 1 | डी, एस, पी, ओ | इकाई=एस, भूमिका='एस', पी=पी | पूर्ण मिलान | परिपूर्ण उपसर्ग |
|
||||
| 2 | डी, एस, पी, ? | इकाई=एस, भूमिका='एस', पी=पी | डी पर फ़िल्टर | विभाजन स्कैन + फ़िल्टर |
|
||||
| 3 | डी, एस, ?, ओ | इकाई=एस, भूमिका='एस' | डी, ओ पर फ़िल्टर | विभाजन स्कैन + फ़िल्टर |
|
||||
| 4 | डी, ?, पी, ओ | इकाई=ओ, भूमिका='ओ', पी=पी | डी पर फ़िल्टर | विभाजन स्कैन + फ़िल्टर |
|
||||
| 5 | ?, एस, पी, ओ | इकाई=एस, भूमिका='एस', पी=पी | ओ पर फ़िल्टर | विभाजन स्कैन + फ़िल्टर |
|
||||
| 6 | डी, एस, ?, ? | इकाई=एस, भूमिका='एस' | डी पर फ़िल्टर | विभाजन स्कैन + फ़िल्टर |
|
||||
| 7 | डी, ?, पी, ? | इकाई=पी, भूमिका='पी' | डी पर फ़िल्टर | विभाजन स्कैन + फ़िल्टर |
|
||||
| 8 | डी, ?, ?, ओ | इकाई=ओ, भूमिका='ओ' | डी पर फ़िल्टर | विभाजन स्कैन + फ़िल्टर |
|
||||
| 9 | ?, एस, पी, ? | इकाई=एस, भूमिका='एस', पी=पी | — | **परिपूर्ण उपसर्ग** |
|
||||
| 10 | ?, एस, ?, ओ | इकाई=एस, भूमिका='एस' | ओ पर फ़िल्टर | विभाजन स्कैन + फ़िल्टर |
|
||||
| 11 | ?, ?, पी, ओ | इकाई=ओ, भूमिका='ओ', पी=पी | — | **परिपूर्ण उपसर्ग** |
|
||||
| 12 | डी, ?, ?, ? | इकाई=डी, भूमिका='जी' | — | **परिपूर्ण उपसर्ग** |
|
||||
| 13 | ?, एस, ?, ? | इकाई=एस, भूमिका='एस' | — | **परिपूर्ण उपसर्ग** |
|
||||
| 14 | ?, ?, पी, ? | इकाई=पी, भूमिका='पी' | — | **परिपूर्ण उपसर्ग** |
|
||||
| 15 | ?, ?, ?, ओ | इकाई=ओ, भूमिका='ओ' | — | **परिपूर्ण उपसर्ग** |
|
||||
| 16 | ?, ?, ?, ? | — | पूर्ण स्कैन | केवल अन्वेषण |
|
||||
|
||||
**मुख्य परिणाम**: 15 गैर-तुच्छ पैटर्नों में से 7 परिपूर्ण क्लस्टरिंग उपसर्ग हिट हैं। शेष 8 एकल-विभाजन रीड हैं जिनमें इन-पार्टिशन फ़िल्टरिंग होती है। प्रत्येक क्वेरी जिसमें कम से कम एक ज्ञात तत्व होता है, वह एक विभाजन कुंजी को हिट करती है।
|
||||
|
||||
पैटर्न 16 (?, ?, ?, ?) व्यवहार में नहीं होता है क्योंकि संग्रह हमेशा निर्दिष्ट होता है, जिससे यह पैटर्न 12 में कम हो जाता है।
|
||||
|
||||
### सामान्य क्वेरी उदाहरण
|
||||
|
||||
**किसी इकाई के बारे में सब कुछ:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice';
|
||||
```
|
||||
|
||||
**किसी इकाई के लिए सभी बाहरी संबंध:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S';
|
||||
```
|
||||
|
||||
**किसी इकाई के लिए विशिष्ट विधेय:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows';
|
||||
```
|
||||
|
||||
**किसी इकाई के लिए लेबल (विशिष्ट भाषा):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'http://www.w3.org/2000/01/rdf-schema#label'
|
||||
AND otype = 'L';
|
||||
```
|
||||
|
||||
फिर, यदि आवश्यक हो, तो `lang = 'en'` एप्लिकेशन-साइड पर फ़िल्टर करें।
|
||||
|
||||
**केवल URI-मान वाले संबंध (इकाई-से-इकाई लिंक):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows' AND otype = 'U';
|
||||
```
|
||||
|
||||
**रिवर्स लुकअप - यह इकाई किससे जुड़ी है:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Bob'
|
||||
AND role = 'O';
|
||||
```
|
||||
|
||||
## लेबल रिज़ॉल्यूशन और कैश वार्मिंग
|
||||
|
||||
एंटिटी-सेंट्रिक मॉडल के सबसे महत्वपूर्ण लाभों में से एक यह है कि **लेबल रिज़ॉल्यूशन एक मुफ्त साइड इफ़ेक्ट बन जाता है।**
|
||||
|
||||
पारंपरिक मल्टी-टेबल मॉडल में, लेबल प्राप्त करने के लिए अलग-अलग राउंड-ट्रिप क्वेरी की आवश्यकता होती है: ट्रिपल प्राप्त करें, परिणामों में एंटिटी यूआरआई की पहचान करें, फिर प्रत्येक के लिए `rdfs:label` प्राप्त करें। यह N+1 पैटर्न महंगा है।
|
||||
|
||||
एंटिटी-सेंट्रिक मॉडल में, किसी एंटिटी को क्वेरी करने पर, यह उसके सभी क्वाड लौटाता है - जिसमें उसके लेबल, प्रकार और अन्य गुण शामिल हैं। जब एप्लिकेशन क्वेरी परिणामों को कैश करता है, तो लेबल किसी भी चीज़ के लिए अनुरोध करने से पहले ही प्री-वार्म हो जाते हैं।
|
||||
|
||||
दो उपयोग परिदृश्य इस बात की पुष्टि करते हैं कि यह व्यवहार में अच्छी तरह से काम करता है:
|
||||
|
||||
**मानव-सामना करने वाली क्वेरी:** स्वाभाविक रूप से छोटे परिणाम सेट, लेबल आवश्यक। एंटिटी रीड कैश को प्री-वार्म करते हैं।
|
||||
**एआई/बल्क क्वेरी:** बड़े परिणाम सेट जिनमें सख्त सीमाएं होती हैं। लेबल या तो अनावश्यक होते हैं या केवल उन एंटिटीज के एक क्यूरेटेड सबसेट के लिए आवश्यक होते हैं जो पहले से ही कैश में हैं।
|
||||
|
||||
30,000 एंटिटीज जैसे विशाल परिणाम सेट के लिए लेबल को हल करने की सैद्धांतिक चिंता को इस व्यावहारिक अवलोकन द्वारा कम किया जाता है कि कोई भी मानव या एआई उपभोक्ता उन सभी लेबलों को उपयोगी रूप से संसाधित नहीं करता है। एप्लिकेशन-स्तरीय क्वेरी सीमाएं यह सुनिश्चित करती हैं कि कैश दबाव प्रबंधनीय रहे।
|
||||
|
||||
## वाइड पार्टिशन्स और रीफिकेशन
|
||||
|
||||
रीफिकेशन (आरडीएफ-स्टार शैली के स्टेटमेंट स्टेटमेंट के बारे में) हब एंटिटीज बनाते हैं - उदाहरण के लिए, एक स्रोत दस्तावेज़ जो निकाले गए हजारों तथ्यों का समर्थन करता है। इससे वाइड पार्टिशन्स बन सकते हैं।
|
||||
|
||||
कम करने वाले कारक:
|
||||
|
||||
**एप्लिकेशन-स्तरीय क्वेरी सीमाएं:** सभी GraphRAG और मानव-सामना करने वाली क्वेरी सख्त सीमाओं को लागू करती हैं, इसलिए हॉट रीड पाथ पर वाइड पार्टिशन्स को कभी भी पूरी तरह से स्कैन नहीं किया जाता है।
|
||||
**कैसेंड्रा आंशिक रीड को कुशलता से संभालता है:** एक क्लस्टरिंग कॉलम स्कैन जिसमें शुरुआती स्टॉप हो, वह बड़े पार्टिशन्स पर भी तेज़ होता है।
|
||||
**कलेक्शन डिलीशन** (केवल वह ऑपरेशन जो पूरे पार्टिशन्स को पार कर सकता है) एक स्वीकृत पृष्ठभूमि प्रक्रिया है।
|
||||
|
||||
## कलेक्शन डिलीशन
|
||||
|
||||
एपीआई कॉल द्वारा ट्रिगर किया गया, पृष्ठभूमि में चलता है (अंततः सुसंगत)।
|
||||
|
||||
1. लक्ष्य कलेक्शन के लिए `quads_by_collection` पढ़ें ताकि सभी क्वाड प्राप्त हो सकें।
|
||||
2. क्वाड से अद्वितीय एंटिटीज निकालें (s, p, o, d मान)।
|
||||
3. प्रत्येक अद्वितीय एंटिटी के लिए, `quads_by_entity` से पार्टीशन को हटाएं।
|
||||
4. `quads_by_collection` से पंक्तियों को हटाएं।
|
||||
|
||||
`quads_by_collection` टेबल वह इंडेक्स प्रदान करता है जिसकी आवश्यकता सभी एंटिटी पार्टिशन्स को खोजने के लिए होती है बिना पूरे टेबल स्कैन के। पार्टीशन-स्तरीय डिलीट कुशल हैं क्योंकि `(collection, entity)` पार्टीशन कुंजी है।
|
||||
|
||||
## मल्टी-टेबल मॉडल से माइग्रेशन पाथ
|
||||
|
||||
एंटिटी-सेंट्रिक मॉडल मौजूदा मल्टी-टेबल मॉडल के साथ माइग्रेशन के दौरान सह-अस्तित्व में रह सकता है:
|
||||
|
||||
1. मौजूदा टेबल के साथ `quads_by_entity` और `quads_by_collection` टेबल तैनात करें।
|
||||
2. नए और पुराने दोनों टेबल में नए क्वाड को डुअल-राइट करें।
|
||||
3. मौजूदा डेटा को नए टेबल में बैकफिल करें।
|
||||
4. एक क्वेरी पैटर्न को एक बार में माइग्रेट करें।
|
||||
5. सभी रीड माइग्रेट होने के बाद पुराने टेबल को डीकमीशन करें।
|
||||
|
||||
## सारांश
|
||||
|
||||
| पहलू | पारंपरिक (6-टेबल) | एंटिटी-सेंट्रिक (2-टेबल) |
|
||||
|---|---|---|
|
||||
| टेबल | 7+ | 2 |
|
||||
| क्वाड प्रति राइट | 6+ | 5 (4 डेटा + 1 मैनिफेस्ट) |
|
||||
| लेबल रिज़ॉल्यूशन | अलग राउंड ट्रिप | कैश वार्मिंग के माध्यम से मुफ्त |
|
||||
| क्वेरी पैटर्न | 6 टेबल में 16 | 1 टेबल में 16 |
|
||||
| स्कीमा जटिलता | उच्च | कम |
|
||||
| परिचालन ओवरहेड | ट्यून/मरम्मत के लिए 6 टेबल | 1 डेटा टेबल |
|
||||
| रीफिकेशन सपोर्ट | अतिरिक्त जटिलता | प्राकृतिक फिट |
|
||||
| ऑब्जेक्ट टाइप फ़िल्टरिंग | उपलब्ध नहीं | देशी (otype क्लस्टरिंग के माध्यम से) |
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Entity-Centric Knowledge Graph Storage on Cassandra"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Entity-Centric Knowledge Graph Storage on Cassandra
|
||||
|
||||
## Overview
|
||||
|
|
@ -258,4 +264,3 @@ The entity-centric model can coexist with the existing multi-table model during
|
|||
| Operational overhead | 6 tables to tune/repair | 1 data table |
|
||||
| Reification support | Additional complexity | Natural fit |
|
||||
| Object type filtering | Not available | Native (via otype clustering) |
|
||||
|
||||
|
|
|
|||
269
docs/tech-specs/entity-centric-graph.pt.md
Normal file
269
docs/tech-specs/entity-centric-graph.pt.md
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Armazenamento de Grafos de Conhecimento Centrados em Entidades no Cassandra"
|
||||
parent: "Portuguese (Beta)"
|
||||
---
|
||||
|
||||
# Armazenamento de Grafos de Conhecimento Centrados em Entidades no Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Este documento descreve um modelo de armazenamento para grafos de conhecimento no estilo RDF no Apache Cassandra. O modelo usa uma abordagem **centrada em entidades**, onde cada entidade conhece cada quádrupla em que participa e o papel que desempenha. Isso substitui uma abordagem tradicional de permutação SPO em várias tabelas por apenas duas tabelas.
|
||||
|
||||
## Contexto e Motivação
|
||||
|
||||
### A Abordagem Tradicional
|
||||
|
||||
Um armazenamento RDF padrão no Cassandra requer várias tabelas desnormalizadas para cobrir padrões de consulta — normalmente 6 ou mais tabelas representando diferentes permutações de Sujeito, Predicado, Objeto e Conjunto de Dados (SPOD). Cada quádrupla é escrita em todas as tabelas, resultando em uma amplificação de escrita significativa, sobrecarga operacional e complexidade do esquema.
|
||||
|
||||
Além disso, a resolução de rótulos (busca de nomes legíveis para humanos para entidades) requer consultas separadas de ida e volta, o que é particularmente caro em casos de uso de IA e GraphRAG, onde os rótulos são essenciais para o contexto do LLM.
|
||||
|
||||
### A Perspectiva Centrada na Entidade
|
||||
|
||||
Cada quádrupla `(D, S, P, O)` envolve até 4 entidades. Ao escrever uma linha para a participação de cada entidade na quádrupla, garantimos que **qualquer consulta com pelo menos um elemento conhecido atingirá uma chave de partição**. Isso cobre todos os 16 padrões de consulta com uma única tabela de dados.
|
||||
|
||||
Benefícios principais:
|
||||
|
||||
**2 tabelas** em vez de 7+
|
||||
**4 gravações por quádrupla** em vez de 6+
|
||||
**Resolução de rótulos gratuita** — os rótulos de uma entidade estão localizados com seus relacionamentos, aquecendo naturalmente o cache da aplicação
|
||||
**Todos os 16 padrões de consulta** atendidos por leituras de partição única
|
||||
**Operações mais simples** — uma única tabela de dados para ajustar, compactar e reparar
|
||||
|
||||
## Esquema
|
||||
|
||||
### Tabela 1: quads_by_entity
|
||||
|
||||
A tabela de dados primária. Cada entidade tem uma partição contendo todas as quádruplas em que participa. Nomeada para refletir o padrão de consulta (busca por entidade).
|
||||
Saída do contrato (deve seguir exatamente o formato abaixo).
|
||||
```sql
|
||||
CREATE TABLE quads_by_entity (
|
||||
collection text, -- Collection/tenant scope (always specified)
|
||||
entity text, -- The entity this row is about
|
||||
role text, -- 'S', 'P', 'O', 'G' — how this entity participates
|
||||
p text, -- Predicate of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
s text, -- Subject of the quad
|
||||
o text, -- Object of the quad
|
||||
d text, -- Dataset/graph of the quad
|
||||
dtype text, -- XSD datatype (when otype = 'L'), e.g. 'xsd:string'
|
||||
lang text, -- Language tag (when otype = 'L'), e.g. 'en', 'fr'
|
||||
PRIMARY KEY ((collection, entity), role, p, otype, s, o, d, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
**Chave de partição**: `(collection, entity)` — restrita à coleção, uma partição por entidade.
|
||||
|
||||
**Justificativa para a ordem das colunas de agrupamento**:
|
||||
|
||||
1. **role** — a maioria das consultas começa com "onde esta entidade é um sujeito/objeto"
|
||||
2. **p** — próximo filtro mais comum, "me dê todas as relações `knows`"
|
||||
3. **otype** — permite filtrar por relações com valor URI versus relações com valor literal
|
||||
4. **s, o, d** — colunas restantes para garantir a unicidade
|
||||
5. **dtype, lang** — distingue literais com o mesmo valor, mas com metadados de tipo diferentes (por exemplo, `"thing"` vs `"thing"@en` vs `"thing"^^xsd:string`)
|
||||
|
||||
### Tabela 2: quads_by_collection
|
||||
|
||||
Suporta consultas e exclusões no nível da coleção. Fornece um manifesto de todos os quads pertencentes a uma coleção. Nomeado para refletir o padrão de consulta (pesquisa por coleção).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_collection (
|
||||
collection text,
|
||||
d text, -- Dataset/graph of the quad
|
||||
s text, -- Subject of the quad
|
||||
p text, -- Predicate of the quad
|
||||
o text, -- Object of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
dtype text, -- XSD datatype (when otype = 'L')
|
||||
lang text, -- Language tag (when otype = 'L')
|
||||
PRIMARY KEY (collection, d, s, p, o, otype, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
Agrupados primeiro por conjunto de dados, permitindo a exclusão em nível de coleção ou de conjunto de dados. As colunas `otype`, `dtype` e `lang` estão incluídas na chave de agrupamento para distinguir literais com o mesmo valor, mas com metadados de tipo diferentes — em RDF, `"thing"`, `"thing"@en` e `"thing"^^xsd:string` são valores semanticamente distintos.
|
||||
|
||||
## Caminho de Escrita
|
||||
|
||||
Para cada quádruplo de entrada `(D, S, P, O)` dentro de uma coleção `C`, escreva **4 linhas** em `quads_by_entity` e **1 linha** em `quads_by_collection`.
|
||||
|
||||
### Exemplo
|
||||
|
||||
Dado o quádruplo na coleção `tenant1`:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: https://example.org/knows
|
||||
Object: https://example.org/Bob
|
||||
```
|
||||
|
||||
Escreva 4 linhas para `quads_by_entity`:
|
||||
|
||||
| collection | entity | role | p | otype | s | o | d |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | G | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Alice | S | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/knows | P | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Bob | O | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
|
||||
Escreva 1 linha para `quads_by_collection`:
|
||||
|
||||
| collection | d | s | p | o | otype | dtype | lang |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | https://example.org/Alice | https://example.org/knows | https://example.org/Bob | U | | |
|
||||
|
||||
### Exemplo Literal
|
||||
|
||||
Para uma tripla de rótulo:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: http://www.w3.org/2000/01/rdf-schema#label
|
||||
Object: "Alice Smith" (lang: en)
|
||||
```
|
||||
|
||||
O `otype` é `'L'`, `dtype` é `'xsd:string'`, e `lang` é `'en'`. O valor literal `"Alice Smith"` é armazenado em `o`. Apenas 3 linhas são necessárias em `quads_by_entity` — nenhuma linha é escrita para o literal como entidade, pois os literais não são entidades consultáveis independentes.
|
||||
|
||||
## Padrões de Consulta
|
||||
|
||||
### Todos os 16 Padrões DSPO
|
||||
|
||||
Na tabela abaixo, "Prefixo perfeito" significa que a consulta usa um prefixo contíguo das colunas de agrupamento. "Leitura de partição + filtro" significa que o Cassandra lê uma fatia de uma partição e filtra na memória — ainda eficiente, mas não uma correspondência de prefixo pura.
|
||||
|
||||
| # | Conhecido | Consulta de entidade | Prefixo de agrupamento | Eficiência |
|
||||
|---|---|---|---|---|
|
||||
| 1 | D,S,P,O | entidade=S, role='S', p=P | Correspondência completa | Prefixo perfeito |
|
||||
| 2 | D,S,P,? | entidade=S, role='S', p=P | Filtro em D | Leitura de partição + filtro |
|
||||
| 3 | D,S,?,O | entidade=S, role='S' | Filtro em D, O | Leitura de partição + filtro |
|
||||
| 4 | D,?,P,O | entidade=O, role='O', p=P | Filtro em D | Leitura de partição + filtro |
|
||||
| 5 | ?,S,P,O | entidade=S, role='S', p=P | Filtro em O | Leitura de partição + filtro |
|
||||
| 6 | D,S,?,? | entidade=S, role='S' | Filtro em D | Leitura de partição + filtro |
|
||||
| 7 | D,?,P,? | entidade=P, role='P' | Filtro em D | Leitura de partição + filtro |
|
||||
| 8 | D,?,?,O | entidade=O, role='O' | Filtro em D | Leitura de partição + filtro |
|
||||
| 9 | ?,S,P,? | entidade=S, role='S', p=P | — | **Prefixo perfeito** |
|
||||
| 10 | ?,S,?,O | entidade=S, role='S' | Filtro em O | Leitura de partição + filtro |
|
||||
| 11 | ?,?,P,O | entidade=O, role='O', p=P | — | **Prefixo perfeito** |
|
||||
| 12 | D,?,?,? | entidade=D, role='G' | — | **Prefixo perfeito** |
|
||||
| 13 | ?,S,?,? | entidade=S, role='S' | — | **Prefixo perfeito** |
|
||||
| 14 | ?,?,P,? | entidade=P, role='P' | — | **Prefixo perfeito** |
|
||||
| 15 | ?,?,?,O | entidade=O, role='O' | — | **Prefixo perfeito** |
|
||||
| 16 | ?,?,?,? | — | Leitura completa | Apenas exploração |
|
||||
|
||||
**Resultado chave**: 7 dos 15 padrões não triviais são correspondências perfeitas de prefixo de agrupamento. Os 8 restantes são leituras de partição única com filtragem dentro da partição. Cada consulta com pelo menos um elemento conhecido atinge uma chave de partição.
|
||||
|
||||
O padrão 16 (?,?,?,?) não ocorre na prática, pois a coleção é sempre especificada, reduzindo-o ao padrão 12.
|
||||
|
||||
### Exemplos Comuns de Consulta
|
||||
|
||||
**Tudo sobre uma entidade:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice';
|
||||
```
|
||||
|
||||
**Todos os relacionamentos de saída para uma entidade:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S';
|
||||
```
|
||||
|
||||
**Predicado específico para uma entidade:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows';
|
||||
```
|
||||
|
||||
**Rótulo para uma entidade (idioma específico):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'http://www.w3.org/2000/01/rdf-schema#label'
|
||||
AND otype = 'L';
|
||||
```
|
||||
|
||||
Em seguida, filtre por aplicação no lado do cliente, se necessário, usando `lang = 'en'`.
|
||||
|
||||
**Apenas relacionamentos com valores URI (links de entidade para entidade):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows' AND otype = 'U';
|
||||
```
|
||||
|
||||
**Pesquisa reversa — o que aponta para esta entidade:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Bob'
|
||||
AND role = 'O';
|
||||
```
|
||||
|
||||
## Resolução de Rótulos e Aquecimento do Cache
|
||||
|
||||
Uma das vantagens mais significativas do modelo centrado em entidades é que **a resolução de rótulos se torna um efeito colateral gratuito**.
|
||||
|
||||
No modelo tradicional de várias tabelas, buscar rótulos requer consultas separadas: recuperar triplas, identificar URIs de entidades nos resultados e, em seguida, buscar `rdfs:label` para cada uma. Esse padrão N+1 é caro.
|
||||
|
||||
No modelo centrado em entidades, consultar uma entidade retorna **todos** os seus quadros — incluindo seus rótulos, tipos e outras propriedades. Quando o aplicativo armazena em cache os resultados das consultas, os rótulos são pré-aquecidos antes que qualquer coisa os solicite.
|
||||
|
||||
Dois regimes de uso confirmam que isso funciona bem na prática:
|
||||
|
||||
**Consultas voltadas para o usuário**: conjuntos de resultados naturalmente pequenos, rótulos essenciais. As leituras de entidades pré-aquecem o cache.
|
||||
**Consultas de IA/em lote**: conjuntos de resultados grandes com limites rígidos. Os rótulos são desnecessários ou necessários apenas para um subconjunto selecionado de entidades que já estão no cache.
|
||||
|
||||
A preocupação teórica de resolver rótulos para conjuntos de resultados enormes (por exemplo, 30.000 entidades) é atenuada pela observação prática de que nenhum usuário humano ou de IA processa tantos rótulos de forma útil. Os limites de consulta no nível da aplicação garantem que a pressão do cache permaneça gerenciável.
|
||||
|
||||
## Partições Largas e Reificação
|
||||
|
||||
A reificação (declarações RDF-star sobre declarações) cria entidades de hub — por exemplo, um documento de origem que suporta milhares de fatos extraídos. Isso pode produzir partições largas.
|
||||
|
||||
Fatores atenuantes:
|
||||
|
||||
**Limites de consulta no nível da aplicação**: todas as consultas do GraphRAG e voltadas para o usuário impõem limites rígidos, portanto, as partições largas nunca são totalmente examinadas no caminho de leitura quente.
|
||||
**O Cassandra lida com leituras parciais de forma eficiente**: uma varredura de coluna de agrupamento com uma parada antecipada é rápida, mesmo em partições grandes.
|
||||
**Exclusão de coleções** (a única operação que pode percorrer partições completas) é um processo de segundo plano aceitável.
|
||||
|
||||
## Exclusão de Coleções
|
||||
|
||||
Acionada por chamada de API, é executada em segundo plano (consistência eventual).
|
||||
|
||||
1. Leia `quads_by_collection` para a coleção de destino para obter todos os quadros.
|
||||
2. Extraia entidades exclusivas das quadros (valores s, p, o, d).
|
||||
3. Para cada entidade exclusiva, exclua a partição de `quads_by_entity`.
|
||||
4. Exclua as linhas de `quads_by_collection`.
|
||||
|
||||
A tabela `quads_by_collection` fornece o índice necessário para localizar todas as partições de entidade sem uma varredura completa da tabela. As exclusões em nível de partição são eficientes porque `(collection, entity)` é a chave da partição.
|
||||
|
||||
## Caminho de Migração do Modelo de Múltiplas Tabelas
|
||||
|
||||
O modelo centrado em entidades pode coexistir com o modelo de múltiplas tabelas existente durante a migração:
|
||||
|
||||
1. Implante as tabelas `quads_by_entity` e `quads_by_collection` junto com as tabelas existentes.
|
||||
2. Escreva em duplicata novas quadros para ambas as tabelas antigas e novas.
|
||||
3. Preencha os dados existentes nas novas tabelas.
|
||||
4. Migre os caminhos de leitura um padrão de consulta por vez.
|
||||
5. Desative as tabelas antigas assim que todos os caminhos de leitura forem migrados.
|
||||
|
||||
## Resumo
|
||||
|
||||
| Aspecto | Tradicional (6 tabelas) | Centrado em entidade (2 tabelas) |
|
||||
|---|---|---|
|
||||
| Tabelas | 7+ | 2 |
|
||||
| Escritas por quadro | 6+ | 5 (4 dados + 1 manifesto) |
|
||||
| Resolução de rótulos | Consultas separadas | Gratuito via aquecimento do cache |
|
||||
| Padrões de consulta | 16 em 6 tabelas | 16 em 1 tabela |
|
||||
| Complexidade do esquema | Alta | Baixa |
|
||||
| Sobrecarga operacional | 6 tabelas para ajustar/reparar | 1 tabela de dados |
|
||||
| Suporte de reificação | Complexidade adicional | Adequação natural |
|
||||
| Filtragem de tipo de objeto | Não disponível | Nativo (via agrupamento de otype) |
|
||||
Saída do contrato (deve seguir exatamente o formato abaixo).
|
||||
268
docs/tech-specs/entity-centric-graph.ru.md
Normal file
268
docs/tech-specs/entity-centric-graph.ru.md
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Хранение графов знаний, ориентированных на сущности, в Cassandra"
|
||||
parent: "Russian (Beta)"
|
||||
---
|
||||
|
||||
# Хранение графов знаний, ориентированных на сущности, в Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Обзор
|
||||
|
||||
Этот документ описывает модель хранения графов знаний в стиле RDF в Apache Cassandra. Модель использует подход, ориентированный на сущности, при котором каждая сущность знает о каждой квадрупле, в которой она участвует, и о роли, которую она играет. Это заменяет традиционный подход с использованием нескольких таблиц и различных перестановок SPO (Subject, Predicate, Object) всего двумя таблицами.
|
||||
|
||||
## Предыстория и мотивация
|
||||
|
||||
### Традиционный подход
|
||||
|
||||
Стандартное хранилище квадруплов RDF в Cassandra требует нескольких денормализованных таблиц для охвата шаблонов запросов — обычно 6 или более таблиц, представляющих различные перестановки Subject, Predicate, Object и Dataset (SPOD). Каждый квадруплет записывается в каждую таблицу, что приводит к значительному увеличению количества операций записи, оперативным издержкам и сложности схемы.
|
||||
|
||||
Кроме того, разрешение меток (получение удобочитаемых имен для сущностей) требует отдельных запросов, что особенно дорого в сценариях использования AI и GraphRAG, где метки необходимы для контекста LLM.
|
||||
|
||||
### Инсайт, ориентированный на сущности
|
||||
|
||||
Каждый квадруплет `(D, S, P, O)` включает до 4 сущностей. Записывая строку для участия каждой сущности в квадруплете, мы гарантируем, что **любой запрос, содержащий хотя бы один известный элемент, попадет в первичный ключ**. Это охватывает все 16 шаблонов запросов с помощью одной таблицы данных.
|
||||
|
||||
Основные преимущества:
|
||||
|
||||
**2 таблицы** вместо 7+
|
||||
**4 записи на квадруплет** вместо 6+
|
||||
**Разрешение меток бесплатно** — метки сущности находятся рядом с ее отношениями, что естественным образом подогревает кэш приложения.
|
||||
**Все 16 шаблонов запросов** обслуживаются с помощью чтения из одной секции.
|
||||
**Более простые операции** — одна таблица данных для настройки, уплотнения и восстановления.
|
||||
|
||||
## Схема
|
||||
|
||||
### Таблица 1: quads_by_entity
|
||||
|
||||
Основная таблица данных. Каждая сущность имеет секцию, содержащую все квадруплеты, в которых она участвует. Названа в соответствии с шаблоном запроса (поиск по сущности).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_entity (
|
||||
collection text, -- Collection/tenant scope (always specified)
|
||||
entity text, -- The entity this row is about
|
||||
role text, -- 'S', 'P', 'O', 'G' — how this entity participates
|
||||
p text, -- Predicate of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
s text, -- Subject of the quad
|
||||
o text, -- Object of the quad
|
||||
d text, -- Dataset/graph of the quad
|
||||
dtype text, -- XSD datatype (when otype = 'L'), e.g. 'xsd:string'
|
||||
lang text, -- Language tag (when otype = 'L'), e.g. 'en', 'fr'
|
||||
PRIMARY KEY ((collection, entity), role, p, otype, s, o, d, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
**Ключ секции (Partition key)**: `(collection, entity)` — ограничен областью действия коллекции, одна секция на сущность.
|
||||
|
||||
**Обоснование порядка столбцов кластеризации**:
|
||||
|
||||
1. **role** — большинство запросов начинаются с "где эта сущность является субъектом/объектом"
|
||||
2. **p** — следующий по частоте фильтр, "верните все `knows` отношения"
|
||||
3. **otype** — позволяет фильтровать по отношениям со значениями URI по сравнению с литеральными значениями
|
||||
4. **s, o, d** — оставшиеся столбцы для обеспечения уникальности
|
||||
5. **dtype, lang** — различают литералы с одинаковым значением, но с разными метаданными типа (например, `"thing"` vs `"thing"@en` vs `"thing"^^xsd:string`)
|
||||
|
||||
### Таблица 2: quads_by_collection
|
||||
|
||||
Поддерживает запросы и удаление на уровне коллекции. Предоставляет список всех квадруплетов, принадлежащих коллекции. Название отражает шаблон запроса (поиск по коллекции).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_collection (
|
||||
collection text,
|
||||
d text, -- Dataset/graph of the quad
|
||||
s text, -- Subject of the quad
|
||||
p text, -- Predicate of the quad
|
||||
o text, -- Object of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
dtype text, -- XSD datatype (when otype = 'L')
|
||||
lang text, -- Language tag (when otype = 'L')
|
||||
PRIMARY KEY (collection, d, s, p, o, otype, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
Группировка сначала по набору данных, что позволяет удалять данные как на уровне коллекции, так и на уровне набора данных. Столбцы `otype`, `dtype` и `lang` включены в ключ группировки для различения литералов с одинаковым значением, но с разными метаданными типа — в RDF, `"thing"`, `"thing"@en` и `"thing"^^xsd:string` являются семантически различными значениями.
|
||||
|
||||
## Путь записи
|
||||
|
||||
Для каждой входящей квадрупли `(D, S, P, O)` в коллекции `C`, записывайте **4 строки** в `quads_by_entity` и **1 строку** в `quads_by_collection`.
|
||||
|
||||
### Пример
|
||||
|
||||
Для квадрупли в коллекции `tenant1`:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: https://example.org/knows
|
||||
Object: https://example.org/Bob
|
||||
```
|
||||
|
||||
Запишите 4 строки в `quads_by_entity`:
|
||||
|
||||
| collection | entity | role | p | otype | s | o | d |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | G | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Alice | S | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/knows | P | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Bob | O | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
|
||||
Запишите 1 строку в `quads_by_collection`:
|
||||
|
||||
| collection | d | s | p | o | otype | dtype | lang |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | https://example.org/Alice | https://example.org/knows | https://example.org/Bob | U | | |
|
||||
|
||||
### Пример с буквальным текстом
|
||||
|
||||
Для тройки меток:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: http://www.w3.org/2000/01/rdf-schema#label
|
||||
Object: "Alice Smith" (lang: en)
|
||||
```
|
||||
|
||||
`otype` — это `'L'`, `dtype` — это `'xsd:string'`, а `lang` — это `'en'`. Литеральное значение `"Alice Smith"` хранится в `o`. В `quads_by_entity` требуется всего 3 строки — строка для литерала как сущности не записывается, поскольку литералы не являются независимыми сущностями, к которым можно обращаться.
|
||||
|
||||
## Шаблоны запросов
|
||||
|
||||
### Все 16 шаблонов DSPO
|
||||
|
||||
В таблице ниже "Идеальный префикс" означает, что запрос использует непрерывный префикс столбцов кластеризации. "Сканирование раздела + фильтрация" означает, что Cassandra считывает часть одного раздела и фильтрует в памяти — это эффективно, но не является чистым совпадением префикса.
|
||||
|
||||
| # | Известно | Поиск сущности | Префикс кластеризации | Эффективность |
|
||||
|---|---|---|---|---|
|
||||
| 1 | D,S,P,O | entity=S, role='S', p=P | Полное совпадение | Идеальный префикс |
|
||||
| 2 | D,S,P,? | entity=S, role='S', p=P | Фильтрация по D | Сканирование раздела + фильтрация |
|
||||
| 3 | D,S,?,O | entity=S, role='S' | Фильтрация по D, O | Сканирование раздела + фильтрация |
|
||||
| 4 | D,?,P,O | entity=O, role='O', p=P | Фильтрация по D | Сканирование раздела + фильтрация |
|
||||
| 5 | ?,S,P,O | entity=S, role='S', p=P | Фильтрация по O | Сканирование раздела + фильтрация |
|
||||
| 6 | D,S,?,? | entity=S, role='S' | Фильтрация по D | Сканирование раздела + фильтрация |
|
||||
| 7 | D,?,P,? | entity=P, role='P' | Фильтрация по D | Сканирование раздела + фильтрация |
|
||||
| 8 | D,?,?,O | entity=O, role='O' | Фильтрация по D | Сканирование раздела + фильтрация |
|
||||
| 9 | ?,S,P,? | entity=S, role='S', p=P | — | **Идеальный префикс** |
|
||||
| 10 | ?,S,?,O | entity=S, role='S' | Фильтрация по O | Сканирование раздела + фильтрация |
|
||||
| 11 | ?,?,P,O | entity=O, role='O', p=P | — | **Идеальный префикс** |
|
||||
| 12 | D,?,?,? | entity=D, role='G' | — | **Идеальный префикс** |
|
||||
| 13 | ?,S,?,? | entity=S, role='S' | — | **Идеальный префикс** |
|
||||
| 14 | ?,?,P,? | entity=P, role='P' | — | **Идеальный префикс** |
|
||||
| 15 | ?,?,?,O | entity=O, role='O' | — | **Идеальный префикс** |
|
||||
| 16 | ?,?,?,? | — | Полное сканирование | Только исследование |
|
||||
|
||||
**Ключевой результат**: 7 из 15 нетривиальных шаблонов являются идеальными совпадениями префикса кластеризации. Оставшиеся 8 — это чтение одного раздела с фильтрацией внутри раздела. Каждый запрос, содержащий хотя бы один известный элемент, соответствует ключу раздела.
|
||||
|
||||
Шаблон 16 (?,?,?,?) не встречается на практике, поскольку коллекция всегда указана, что сводит его к шаблону 12.
|
||||
|
||||
### Примеры распространенных запросов
|
||||
|
||||
**Вся информация об сущности:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice';
|
||||
```
|
||||
|
||||
**Все исходящие связи для сущности:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S';
|
||||
```
|
||||
|
||||
**Конкретный предикат для сущности:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows';
|
||||
```
|
||||
|
||||
**Метка для сущности (на конкретном языке):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'http://www.w3.org/2000/01/rdf-schema#label'
|
||||
AND otype = 'L';
|
||||
```
|
||||
|
||||
Затем, при необходимости, выполните фильтрацию на стороне приложения с использованием `lang = 'en'`.
|
||||
|
||||
**Только связи, имеющие значение URI (ссылки между сущностями):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows' AND otype = 'U';
|
||||
```
|
||||
|
||||
**Обратный поиск — что указывает на эту сущность:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Bob'
|
||||
AND role = 'O';
|
||||
```
|
||||
|
||||
## Разрешение меток и предварительная загрузка кэша
|
||||
|
||||
Одним из наиболее значительных преимуществ модели, ориентированной на сущности, является то, что **разрешение меток становится побочным эффектом**.
|
||||
|
||||
В традиционной многотабличной модели получение меток требует отдельных запросов: извлечение троек, определение URI сущностей в результатах, а затем получение `rdfs:label` для каждого. Этот шаблон N+1 дорог.
|
||||
|
||||
В модели, ориентированной на сущности, запрос сущности возвращает **все** ее квадруплеты, включая ее метки, типы и другие свойства. Когда приложение кэширует результаты запросов, метки предварительно загружаются в кэш до того, как кто-либо запросит их.
|
||||
|
||||
Два режима использования подтверждают, что это хорошо работает на практике:
|
||||
|
||||
**Запросы, предназначенные для пользователей**: обычно небольшие наборы результатов, метки необходимы. Чтение сущностей предварительно загружает кэш.
|
||||
**Запросы для ИИ/пакетной обработки**: большие наборы результатов с жесткими ограничениями. Метки либо не нужны, либо необходимы только для курированного подмножества сущностей, которые уже находятся в кэше.
|
||||
|
||||
Теоретическое опасение по поводу разрешения меток для огромных наборов результатов (например, 30 000 сущностей) нивелируется практическим наблюдением, что ни один пользователь или ИИ не обрабатывает такое большое количество меток. Ограничения на запросы на уровне приложения обеспечивают, чтобы нагрузка на кэш оставалась управляемой.
|
||||
|
||||
## Широкие разделы и реификация
|
||||
|
||||
Реификация (утверждения RDF-star об утверждениях) создает центральные сущности, например, документ-источник, который поддерживает тысячи извлеченных фактов. Это может привести к широким разделам.
|
||||
|
||||
Факторы, смягчающие ситуацию:
|
||||
|
||||
**Ограничения на запросы на уровне приложения**: все запросы GraphRAG и предназначенные для пользователей применяют жесткие ограничения, поэтому широкие разделы никогда не сканируются полностью на пути горячего чтения.
|
||||
**Cassandra эффективно обрабатывает частичные чтения**: сканирование кластерной колонки с ранней остановкой происходит быстро даже на больших разделах.
|
||||
**Удаление коллекции** (единственная операция, которая может просматривать полные разделы) является приемлемым фоновым процессом.
|
||||
|
||||
## Удаление коллекции
|
||||
|
||||
Запускается по API-вызову, выполняется в фоновом режиме (с конечной согласованностью).
|
||||
|
||||
1. Чтение `quads_by_collection` для целевой коллекции, чтобы получить все квадруплеты.
|
||||
2. Извлечение уникальных сущностей из квадруплетов (значений s, p, o, d).
|
||||
3. Для каждой уникальной сущности удалите раздел из `quads_by_entity`.
|
||||
4. Удалите строки из `quads_by_collection`.
|
||||
|
||||
Таблица `quads_by_collection` предоставляет индекс, необходимый для поиска всех разделов сущностей без полного сканирования таблицы. Удаление на уровне раздела эффективно, поскольку `(collection, entity)` является ключом раздела.
|
||||
|
||||
## Путь миграции из многотабличной модели
|
||||
|
||||
Модель, ориентированная на сущности, может сосуществовать с существующей многотабличной моделью во время миграции:
|
||||
|
||||
1. Разверните таблицы `quads_by_entity` и `quads_by_collection` рядом с существующими таблицами.
|
||||
2. Записывайте новые квадруплеты одновременно в старые и новые таблицы.
|
||||
3. Заполните существующие данные в новые таблицы.
|
||||
4. Мигрируйте пути запросов по одному шаблону за раз.
|
||||
5. Отключите старые таблицы после миграции всех запросов.
|
||||
|
||||
## Краткое описание
|
||||
|
||||
| Аспект | Традиционная (6 таблиц) | Ориентированная на сущности (2 таблицы) |
|
||||
|---|---|---|
|
||||
| Таблицы | 7+ | 2 |
|
||||
| Записи на квадруплет | 6+ | 5 (4 данных + 1 манифест) |
|
||||
| Разрешение меток | Отдельные запросы | Бесплатно благодаря предварительной загрузке кэша |
|
||||
| Шаблоны запросов | 16 по 6 таблицам | 16 на 1 таблицу |
|
||||
| Сложность схемы | Высокая | Низкая |
|
||||
| Операционные накладные расходы | 6 таблиц для настройки/восстановления | 1 таблица данных |
|
||||
| Поддержка реификации | Дополнительная сложность | Естественная совместимость |
|
||||
| Фильтрация по типу объекта | Недоступно | Нативно (через кластеризацию по типу объекта) |
|
||||
268
docs/tech-specs/entity-centric-graph.sw.md
Normal file
268
docs/tech-specs/entity-centric-graph.sw.md
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Uhifadhi wa Mfumo wa Maarifa unaozingatia Vitu kwenye Cassandra"
|
||||
parent: "Swahili (Beta)"
|
||||
---
|
||||
|
||||
# Uhifadhi wa Mfumo wa Maarifa unaozingatia Vitu kwenye Cassandra
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Muhtasari
|
||||
|
||||
Hati hii inaelezea mfumo wa uhifadhi wa mifumo ya maarifa ya mtindo wa RDF kwenye Apache Cassandra. Mfumo hutumia mbinu inayozingatia **vitu**, ambapo kila kitu kinajua kila nne (quad) ambacho kinashiriki na jukumu ambalo linacheza. Hii inabadilisha mbinu ya awali ya meza nyingi zinazobadilisha mpangilio wa SPO kuwa meza mbili tu.
|
||||
|
||||
## Asili na Lengo
|
||||
|
||||
### Mbinu ya Jadi
|
||||
|
||||
Hifadhi ya kawaida ya nne (quad) ya RDF kwenye Cassandra inahitaji meza nyingi zisizofaa ili kufidia mitindo ya maswali — kwa kawaida meza 6 au zaidi zinazowakilisha mabadiliko tofauti ya Mada (Subject), Kielelezo (Predicate), Kitu (Object), na Kundi (Dataset) (SPOD). Kila nne (quad) imeandikwa kwenye kila meza, na kusababisha ongezeko kubwa la uandishi, gharama za uendeshaji, na utata wa muundo.
|
||||
|
||||
Zaidi ya hayo, utatuzi wa lebo (kupata majina yanayoweza kusomwa kwa urahisi kwa vitu) inahitaji maswali ya ziada, ambayo ni ya gharama kubwa hasa katika matumizi ya AI na GraphRAG ambapo lebo ni muhimu kwa muktadha wa LLM.
|
||||
|
||||
### Mwangaza wa Mbinu inayozingatia Vitu
|
||||
|
||||
Kila kikundi cha `(D, S, P, O)` kinahusisha hadi vitu 4. Kwa kuandika safu kwa kila shiriki la kitu katika kikundi, tunahakikisha kwamba **maswali yoyote yenye angalau kipengele kimoja kinachojulikana yatatumia ufunguo wa sehemu**. Hii inafunika mifumo yote 16 ya maswali na jedwali moja la data.
|
||||
|
||||
Faida kuu:
|
||||
|
||||
**Jedwali 2** badala ya 7+
|
||||
**Hali 4 kwa kila kikundi** badala ya 6+
|
||||
**Utatuzi wa lebo bila malipo** — lebo za kitu ziko karibu na uhusiano wake, na hivyo kuongeza kasi ya kumbukumbu ya programu.
|
||||
**Mifumo yote 16 ya maswali** hutumika kwa usomaji wa sehemu moja.
|
||||
**Utendaji rahisi** — jedwali moja la data ili kurekebisha, kupunguza, na kurekebisha.
|
||||
|
||||
## Mpango
|
||||
|
||||
### Jedwali 1: quads_by_entity
|
||||
|
||||
Jedwali kuu la data. Kila kitu kina sehemu inayoyakilisha vikundi vyote ambavyo kitu hicho kinashiriki. Jina lake linaonyesha mfumo wa swali (utafutaji kwa kutumia kitu).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_entity (
|
||||
collection text, -- Collection/tenant scope (always specified)
|
||||
entity text, -- The entity this row is about
|
||||
role text, -- 'S', 'P', 'O', 'G' — how this entity participates
|
||||
p text, -- Predicate of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
s text, -- Subject of the quad
|
||||
o text, -- Object of the quad
|
||||
d text, -- Dataset/graph of the quad
|
||||
dtype text, -- XSD datatype (when otype = 'L'), e.g. 'xsd:string'
|
||||
lang text, -- Language tag (when otype = 'L'), e.g. 'en', 'fr'
|
||||
PRIMARY KEY ((collection, entity), role, p, otype, s, o, d, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
**Ufunguo wa partition:** `(collection, entity)` — unafichwa kwa mkusanyiko, na partition moja kwa kila entiti.
|
||||
|
||||
**Mazingira ya utaratibu wa safu za kuunganisha (clustering):**
|
||||
|
||||
1. **role** — maswali mengi huanza kwa "entiti hii ni mada/jambo"
|
||||
2. **p** — chujio cha kawaida cha pili, "nipa uhusiano wote wa `knows`"
|
||||
3. **otype** — inaruhusu kuchujwa kwa uhusiano wenye thamani ya URI dhidi ya uhusiano wenye thamani ya moja kwa moja
|
||||
4. **s, o, d** — safu zilizobaki kwa uhakikisho
|
||||
5. **dtype, lang** — hutofautisha maandishi yenye thamani sawa lakini metadata tofauti ya aina (k.m., `"thing"` vs `"thing"@en` vs `"thing"^^xsd:string`)
|
||||
|
||||
### Jedwali 2: quads_by_collection
|
||||
|
||||
Inasaidia maswali na uondoaji wa kiwango cha mkusanyiko. Inatoa orodha ya quads zote zinazohusiana na mkusanyiko. Imejina ili kuonyesha muundo wa swali (utafutaji kwa mkusanyiko).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_collection (
|
||||
collection text,
|
||||
d text, -- Dataset/graph of the quad
|
||||
s text, -- Subject of the quad
|
||||
p text, -- Predicate of the quad
|
||||
o text, -- Object of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
dtype text, -- XSD datatype (when otype = 'L')
|
||||
lang text, -- Language tag (when otype = 'L')
|
||||
PRIMARY KEY (collection, d, s, p, o, otype, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
Imefunganishwa kwanza kwa muundo wa data, na hivyo kuruhusu kufutwa kwa vitu au muundo wa data. Safu za `otype`, `dtype`, na `lang` zimejumuishwa katika ufunganishi ili kutofautisha vipengele ambavyo vina thamani sawa lakini data tofauti — katika RDF, `"thing"`, `"thing"@en`, na `"thing"^^xsd:string` ni thamani tofauti kwa maana.
|
||||
|
||||
## Njia ya Kuandika
|
||||
|
||||
Kwa kila kipengele kinachokuja `(D, S, P, O)` ndani ya mkusanyiko `C`, andika **safu 4** kwenye `quads_by_entity` na **safu 1** kwenye `quads_by_collection`.
|
||||
|
||||
### Mfano
|
||||
|
||||
Ikiwa kuna kipengele katika mkusanyiko `tenant1`:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: https://example.org/knows
|
||||
Object: https://example.org/Bob
|
||||
```
|
||||
|
||||
Andika mistari 4 hadi `quads_by_entity`:
|
||||
|
||||
| mkusanyiko | kitu | jukumu | p | aina ya kitu | s | o | d |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | G | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Alice | S | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/knows | P | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Bob | O | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
|
||||
Andika mstari 1 hadi `quads_by_collection`:
|
||||
|
||||
| mkusanyiko | d | s | p | o | aina ya kitu | aina ya data | lugha |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | https://example.org/Alice | https://example.org/knows | https://example.org/Bob | U | | |
|
||||
|
||||
### Mfano Halisi
|
||||
|
||||
Kwa jozi ya lebo:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: http://www.w3.org/2000/01/rdf-schema#label
|
||||
Object: "Alice Smith" (lang: en)
|
||||
```
|
||||
|
||||
Msimbo `otype` ni `'L'`, `dtype` ni `'xsd:string'`, na `lang` ni `'en'`. Thamani halisi `"Alice Smith"` huhifadhiwa katika `o`. Safu 3 tu zinahitajika katika `quads_by_entity` — hakuna safu inayorekodiwa kwa thamani kama kitu, kwa sababu vitu haviwezi kuchunguzwa kando.
|
||||
|
||||
## Mifumo ya Uchunguzi
|
||||
|
||||
### Mifumo 16 Yote ya DSPO
|
||||
|
||||
Katika meza iliyo hapa chini, "Kielelezo kamili" ina maana kwamba swali hutumia kielelezo cha kuendelea cha safu za kuunganisha. "Ufuatiliaji wa sehemu + chujio" ina maana kwamba Cassandra husoma sehemu ya moja ya sehemu na kuchuja katika kumbukumbu — bado ni ufanisi, lakini sio mechi ya kielelezo safi.
|
||||
|
||||
| # | Inajulikana | Tafuta kitu | Kielelezo cha kuunganisha | Ufanisi |
|
||||
|---|---|---|---|---|
|
||||
| 1 | D,S,P,O | kitu=S, jukumu='S', p=P | Mechi kamili | Kielelezo kamili |
|
||||
| 2 | D,S,P,? | kitu=S, jukumu='S', p=P | Chujio kwenye D | Ufuatiliaji wa sehemu + chujio |
|
||||
| 3 | D,S,?,O | kitu=S, jukumu='S' | Chujio kwenye D, O | Ufuatiliaji wa sehemu + chujio |
|
||||
| 4 | D,?,P,O | kitu=O, jukumu='O', p=P | Chujio kwenye D | Ufuatiliaji wa sehemu + chujio |
|
||||
| 5 | ?,S,P,O | kitu=S, jukumu='S', p=P | Chujio kwenye O | Ufuatiliaji wa sehemu + chujio |
|
||||
| 6 | D,S,?,? | kitu=S, jukumu='S' | Chujio kwenye D | Ufuatiliaji wa sehemu + chujio |
|
||||
| 7 | D,?,P,? | kitu=P, jukumu='P' | Chujio kwenye D | Ufuatiliaji wa sehemu + chujio |
|
||||
| 8 | D,?,?,O | kitu=O, jukumu='O' | Chujio kwenye D | Ufuatiliaji wa sehemu + chujio |
|
||||
| 9 | ?,S,P,? | kitu=S, jukumu='S', p=P | — | **Kielelezo kamili** |
|
||||
| 10 | ?,S,?,O | kitu=S, jukumu='S' | Chujio kwenye O | Ufuatiliaji wa sehemu + chujio |
|
||||
| 11 | ?,?,P,O | kitu=O, jukumu='O', p=P | — | **Kielelezo kamili** |
|
||||
| 12 | D,?,?,? | kitu=D, jukumu='G' | — | **Kielelezo kamili** |
|
||||
| 13 | ?,S,?,? | kitu=S, jukumu='S' | — | **Kielelezo kamili** |
|
||||
| 14 | ?,?,P,? | kitu=P, jukumu='P' | — | **Kielelezo kamili** |
|
||||
| 15 | ?,?,?,O | kitu=O, jukumu='O' | — | **Kielelezo kamili** |
|
||||
| 16 | ?,?,?,? | — | Ufuatiliaji kamili | Uchunguzi tu |
|
||||
|
||||
**Matokeo muhimu**: 7 kati ya mifumo 15 isiyo ya kawaida ni mechi kamili za kielelezo cha kuunganisha. Mifumo 8 iliyobaki ni usomaji wa sehemu moja na chujio ndani ya sehemu. Kila swali lenye kipengele kinachojulikana hupiga ufunguo wa sehemu.
|
||||
|
||||
Mfumo 16 (?,?,?,?) haujulikani katika mazoezi kwa sababu mkusanyiko daima umeelezwa, na hivyo kuifanya iwe mfumo wa 12.
|
||||
|
||||
### Mifano ya kawaida ya swali
|
||||
|
||||
**Kila kitu kuhusu kitu:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice';
|
||||
```
|
||||
|
||||
**Uhusiano wote unaotoka kwa kitu:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S';
|
||||
```
|
||||
|
||||
**Tabia maalum ya kitu:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows';
|
||||
```
|
||||
|
||||
**KILabeli kwa kitu (lugha mahususi):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'http://www.w3.org/2000/01/rdf-schema#label'
|
||||
AND otype = 'L';
|
||||
```
|
||||
|
||||
Kisha, chambua matokeo kwa kutumia `lang = 'en'` upande wa programu, ikiwa ni lazima.
|
||||
|
||||
**Tu uhusiano ambao una thamani ya URI (viungo vya aina ya kitu-kwa-kitu):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows' AND otype = 'U';
|
||||
```
|
||||
|
||||
**Utafutaji wa kurudi nyuma — ni nini kinachoelekeza kwenye kitu hiki:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Bob'
|
||||
AND role = 'O';
|
||||
```
|
||||
|
||||
## Utatuzi wa Lebo na Ukaushaji wa Kumbukumbu (Cache Warming)
|
||||
|
||||
Moja ya faida muhimu zaidi ya mfumo unaozingatia vitu (entity-centric) ni kwamba **utatuzi wa lebo unakuwa matokeo ya ziada**.
|
||||
|
||||
Katika mfumo wa zamani unaojumuisha meza nyingi, kupata lebo inahitaji maswali tofauti: pata triplet, tambua URI za vitu katika matokeo, kisha pata `rdfs:label` kwa kila moja. Mfumo huu wa N+1 ni ghali.
|
||||
|
||||
Katika mfumo unaozingatia vitu, kuhoji kitu hurejesha **quads zote** - ikiwa ni pamoja na lebo zake, aina, na sifa zingine. Wakati programu inahifadhi matokeo ya maswali, lebo zimeandaliwa kabla ya chochote kuomba.
|
||||
|
||||
Sera mbili za matumizi zinaonyesha kwamba hii inafanya kazi vizuri katika mazoezi:
|
||||
|
||||
**Maswali yanayoeleweka na binadamu**: kawaida matokeo madogo, lebo ni muhimu. Maswali ya vitu huandalia kumbukumbu (cache).
|
||||
**Maswali ya AI/wingi**: matokeo makubwa na mipaka ngumu. Lebo ama hazihitajiki au zinahitajika tu kwa sehemu ndogo ya vitu ambavyo tayari viko kwenye kumbukumbu.
|
||||
|
||||
Wasiwasi wa kisia wa kutatua lebo kwa matokeo makubwa (k.m. vitu 30,000) hupunguzwa na utambuzi wa vitendo kwamba hakuna mtumiaji wa binadamu au AI anayeweza kuchakata lebo nyingi. Mipaka ya programu ya maswali inahakikisha kwamba shinikizo la kumbukumbu linabaki linaloweza kudhibitiwa.
|
||||
|
||||
## Sehemu Zinazopaswa Kusambazwa na Ufafanuzi
|
||||
|
||||
Ufafanuzi (taarifa za aina ya RDF-star kuhusu taarifa) huunda vitu vya kitovu - k.m. hati ya chanzo ambayo inasaidia ukweli mwingi uliotolewa. Hii inaweza kuzalisha sehemu zinazopaswa kusambazwa.
|
||||
|
||||
Mambo yanayoweza kupunguza:
|
||||
|
||||
**Mipaka ya maswali ya programu**: maswali yote ya GraphRAG na yale yanayoeleweka na binadamu yana mipaka ngumu, kwa hivyo sehemu zinazopaswa kusambazwa hazisomwi kamwe kwa upeo wa njia ya usomaji.
|
||||
**Cassandra inashughulikia usomaji wa sehemu kwa ufanisi**: uchanganuzi wa safu ya ufunguo wa uainishaji na kusimamishwa mapema ni wa haraka hata kwenye sehemu kubwa.
|
||||
**Ufutaji wa mkusanyiko** (operesheni pekee ambayo inaweza kuvuka sehemu kamili) ni mchakato unaokubalika wa asili.
|
||||
|
||||
## Ufufuo wa Mkusaniko
|
||||
|
||||
Huendeshwa na wito wa API, inafanya kazi kwa asili (inatimiza kwa wakati).
|
||||
|
||||
1. Soma `quads_by_collection` kwa mkusanyiko unaolengwa ili kupata quads zote.
|
||||
2. Toa vitu vya kipekee kutoka kwa quads (mahesabu ya s, p, o, d).
|
||||
3. Kwa kila kitu cha kipekee, futa sehemu kutoka kwa `quads_by_entity`.
|
||||
4. Futa mistari kutoka kwa `quads_by_collection`.
|
||||
|
||||
Jedwali la `quads_by_collection` hutoa fahirisi inayohitajika ili kupata sehemu zote za kitu bila uchanganuzi kamili wa jedwali. Ufufuo wa kiwango cha sehemu ni wa ufanisi kwa sababu `(collection, entity)` ndio ufunguo wa sehemu.
|
||||
|
||||
## Njia ya Uhamishaji kutoka kwa Mfumo wa Meza Nyingi
|
||||
|
||||
Mfumo unaozingatia vitu unaweza kuwepo na mfumo wa zamani unaojumuisha meza nyingi wakati wa uhamishaji:
|
||||
|
||||
1. Weka meza za `quads_by_entity` na `quads_by_collection` pamoja na meza zilizopo.
|
||||
2. Andika quads mpya kwa meza zote mbili za zamani na mpya.
|
||||
3. Jaza data iliyopo kwenye meza mpya.
|
||||
4. Hamisha njia za maswali moja kwa moja.
|
||||
5. Ondoa meza za zamani baada ya maswali yote kuhamishwa.
|
||||
|
||||
## Muhtasari
|
||||
|
||||
| Nguvu | Zamani (meza 6) | Kitu (meza 2) |
|
||||
|---|---|---|
|
||||
| Meza | 7+ | 2 |
|
||||
| Andishi kwa kila quad | 6+ | 5 (4 data + 1 manifest) |
|
||||
| Utafiti wa lebo | Safari tofauti | Bila shida kupitia ukaushaji wa kumbukumbu |
|
||||
| Mfumo wa maswali | 16 katika meza 6 | 16 katika meza 1 |
|
||||
| Ufumbuzi wa mpango | Wa juu | Wa chini |
|
||||
| Uendeshaji | Meza 6 za kurekebisha/kufufua | Jedwali 1 la data |
|
||||
| Usaidizi wa ufafanuzi | Ufumbuzi wa ziada | Inafaa asili |
|
||||
| Uchunguzi wa aina ya kitu | Haipatikani | Asili (kupitia uainishaji wa otype) |
|
||||
269
docs/tech-specs/entity-centric-graph.tr.md
Normal file
269
docs/tech-specs/entity-centric-graph.tr.md
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Cassandra'da Varlık Odaklı Bilgi Grafiği Depolama"
|
||||
parent: "Turkish (Beta)"
|
||||
---
|
||||
|
||||
# Cassandra'da Varlık Odaklı Bilgi Grafiği Depolama
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Genel Bakış
|
||||
|
||||
Bu belge, Apache Cassandra üzerindeki RDF tarzı bilgi grafiklerinin depolanması için bir model tanımlamaktadır. Model, her varlığın katıldığı her dörtlü hakkında bilgi sahibi olduğu ve oynadığı rolün bilindiği, **varlık odaklı** bir yaklaşım kullanır. Bu, geleneksel çok tablolu SPO permütasyon yaklaşımının yerini sadece iki tabloyla alır.
|
||||
|
||||
## Arka Plan ve Motivasyon
|
||||
|
||||
### Geleneksel Yaklaşım
|
||||
|
||||
Cassandra'daki standart bir RDF dörtlü deposu, sorgu kalıplarını kapsamak için birden fazla denormalize edilmiş tablo gerektirir; tipik olarak, Konu, Özne, Nesne ve Veri Kümesi (SPOD) permütasyonlarının farklı temsillerini içeren 6 veya daha fazla tablo. Her dörtlü, her tabloya yazılır, bu da önemli bir yazma çoğaltmasına, operasyonel yüke ve şema karmaşıklığına yol açar.
|
||||
|
||||
Ek olarak, etiket çözümü (varlıklar için okunabilir adların alınması), ayrı gidiş-dönüş sorguları gerektirir ve bu da, etiketlerin LLM bağlamı için önemli olduğu yapay zeka ve GraphRAG kullanım durumlarında özellikle maliyetlidir.
|
||||
|
||||
### Varlık Odaklı İçgörü
|
||||
|
||||
Her bir dörtlü `(D, S, P, O)`, en fazla 4 varlığı içerir. Her bir varlığın dörtlüdeki katılımını bir satırla belirterek, **en az bir bilinen öğesi olan her sorgunun bir bölüm anahtarını hedefleyeceğinden emin oluruz**. Bu, tek bir veri tablosuyla tüm 16 sorgu desenini kapsar.
|
||||
|
||||
Temel avantajlar:
|
||||
|
||||
**7'den fazla yerine 2 tablo**
|
||||
**6'dan fazla yerine, her dörtlü için 4 yazma işlemi**
|
||||
**Etiket çözümlemesi ücretsiz** — bir varlığın etiketleri, ilişkileriyle birlikte bulunur ve bu da uygulama önbelleğini doğal olarak önceden doldurur.
|
||||
**Tüm 16 sorgu deseni**, tek bölüm okumalarıyla sağlanır.
|
||||
**Daha basit işlemler** — ayarlanması, sıkıştırılması ve onarılması gereken tek bir veri tablosu.
|
||||
|
||||
## Şema
|
||||
|
||||
### Tablo 1: quads_by_entity
|
||||
|
||||
Birincil veri tablosu. Her varlığın, katıldığı tüm dörtlüleri içeren bir bölümü vardır. Sorgu desenini yansıtacak şekilde adlandırılmıştır (varlık bazında arama).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_entity (
|
||||
collection text, -- Collection/tenant scope (always specified)
|
||||
entity text, -- The entity this row is about
|
||||
role text, -- 'S', 'P', 'O', 'G' — how this entity participates
|
||||
p text, -- Predicate of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
s text, -- Subject of the quad
|
||||
o text, -- Object of the quad
|
||||
d text, -- Dataset/graph of the quad
|
||||
dtype text, -- XSD datatype (when otype = 'L'), e.g. 'xsd:string'
|
||||
lang text, -- Language tag (when otype = 'L'), e.g. 'en', 'fr'
|
||||
PRIMARY KEY ((collection, entity), role, p, otype, s, o, d, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
**Bölüm anahtarı**: `(collection, entity)` — koleksiyona özel, her varlık için bir bölüm.
|
||||
|
||||
**Kümeleme sütun sıralama gerekçesi**:
|
||||
|
||||
1. **role** — çoğu sorgu, "bu varlık bir konu mu/nesne mi" şeklinde başlar.
|
||||
2. **p** — en yaygın filtrelerden ikincisi, "bana tüm `knows` ilişkilerini ver".
|
||||
3. **otype** — URI değeri olan ilişkileri, literal değeri olan ilişkilerden ayırmayı sağlar.
|
||||
4. **s, o, d** — benzersizlik için kalan sütunlar.
|
||||
5. **dtype, lang** — aynı değere sahip ancak farklı tür meta verilerine sahip literal değerleri ayırt eder (örneğin, `"thing"` vs `"thing"@en` vs `"thing"^^xsd:string`).
|
||||
|
||||
### Tablo 2: quads_by_collection
|
||||
|
||||
Koleksiyon seviyesindeki sorguları ve silme işlemlerini destekler. Bir koleksiyona ait olan tüm dörtlülerin bir listesini sağlar. Sorgu desenini yansıtacak şekilde adlandırılmıştır (koleksiyona göre arama).
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_collection (
|
||||
collection text,
|
||||
d text, -- Dataset/graph of the quad
|
||||
s text, -- Subject of the quad
|
||||
p text, -- Predicate of the quad
|
||||
o text, -- Object of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
dtype text, -- XSD datatype (when otype = 'L')
|
||||
lang text, -- Language tag (when otype = 'L')
|
||||
PRIMARY KEY (collection, d, s, p, o, otype, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
İlk olarak veri kümesi bazında gruplandırılır, bu da silme işleminin ya koleksiyon düzeyinde ya da veri kümesi düzeyinde yapılabilmesini sağlar. `otype`, `dtype` ve `lang` sütunları, aynı değere sahip ancak farklı tür meta verilerine sahip literal değerleri ayırt etmek için kümeleme anahtarına dahil edilmiştir; RDF'de, `"thing"`, `"thing"@en` ve `"thing"^^xsd:string` semantik olarak farklı değerlerdir.
|
||||
|
||||
## Yazma Yolu
|
||||
|
||||
Her bir koleksiyon içindeki `C` içinde gelen `(D, S, P, O)` dörtlüsü için, **4 satır** `quads_by_entity`'ye ve **1 satır** `quads_by_collection`'e yazın.
|
||||
|
||||
### Örnek
|
||||
|
||||
Koleksiyon içindeki `tenant1` dörtgeni verildiğinde:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: https://example.org/knows
|
||||
Object: https://example.org/Bob
|
||||
```
|
||||
|
||||
`quads_by_entity`'e 4 satır yazın:
|
||||
|
||||
| collection | entity | role | p | otype | s | o | d |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | G | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Alice | S | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/knows | P | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Bob | O | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
|
||||
`quads_by_collection`'e 1 satır yazın:
|
||||
|
||||
| collection | d | s | p | o | otype | dtype | lang |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | https://example.org/Alice | https://example.org/knows | https://example.org/Bob | U | | |
|
||||
|
||||
### Literal Example
|
||||
|
||||
Bir etiket üçlüsü için:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: http://www.w3.org/2000/01/rdf-schema#label
|
||||
Object: "Alice Smith" (lang: en)
|
||||
```
|
||||
|
||||
`otype` değeri `'L'`, `dtype` değeri `'xsd:string'` ve `lang` değeri `'en'`'tir. Literal değer olan `"Alice Smith"`, `o` içinde saklanır. `quads_by_entity`'de yalnızca 3 satır gereklidir; literal, bir varlık olarak bağımsız olarak sorgulanamayan bir şey olduğu için, literal için herhangi bir satır yazılmaz.
|
||||
|
||||
## Sorgu Desenleri
|
||||
|
||||
### Tüm 16 DSPO Deseni
|
||||
|
||||
Aşağıdaki tabloda, "Mükemmel önek", sorgunun kümeleme sütunlarının ardışık bir önekini kullandığı anlamına gelir. "Bölüm taraması + filtre", Cassandra'nın bir bölümün bir dilimini okuduğu ve bellekte filtreleme yaptığı anlamına gelir; bu, verimli olsa da, saf bir önek eşleşmesi değildir.
|
||||
|
||||
| # | Bilinen | Varlık | Kümeleme öneki | Verimlilik |
|
||||
|---|---|---|---|---|
|
||||
| 1 | D,S,P,O | entity=S, role='S', p=P | Tam eşleşme | Mükemmel önek |
|
||||
| 2 | D,S,P,? | entity=S, role='S', p=P | D üzerinde filtreleme | Bölüm taraması + filtre |
|
||||
| 3 | D,S,?,O | entity=S, role='S' | D, O üzerinde filtreleme | Bölüm taraması + filtre |
|
||||
| 4 | D,?,P,O | entity=O, role='O', p=P | D üzerinde filtreleme | Bölüm taraması + filtre |
|
||||
| 5 | ?,S,P,O | entity=S, role='S', p=P | O üzerinde filtreleme | Bölüm taraması + filtre |
|
||||
| 6 | D,S,?,? | entity=S, role='S' | D üzerinde filtreleme | Bölüm taraması + filtre |
|
||||
| 7 | D,?,P,? | entity=P, role='P' | D üzerinde filtreleme | Bölüm taraması + filtre |
|
||||
| 8 | D,?,?,O | entity=O, role='O' | D üzerinde filtreleme | Bölüm taraması + filtre |
|
||||
| 9 | ?,S,P,? | entity=S, role='S', p=P | — | **Mükemmel önek** |
|
||||
| 10 | ?,S,?,O | entity=S, role='S' | O üzerinde filtreleme | Bölüm taraması + filtre |
|
||||
| 11 | ?,?,P,O | entity=O, role='O', p=P | — | **Mükemmel önek** |
|
||||
| 12 | D,?,?,? | entity=D, role='G' | — | **Mükemmel önek** |
|
||||
| 13 | ?,S,?,? | entity=S, role='S' | — | **Mükemmel önek** |
|
||||
| 14 | ?,?,P,? | entity=P, role='P' | — | **Mükemmel önek** |
|
||||
| 15 | ?,?,?,O | entity=O, role='O' | — | **Mükemmel önek** |
|
||||
| 16 | ?,?,?,? | — | Tam tarama | Yalnızca keşif |
|
||||
|
||||
**Önemli sonuç**: 15 önemsiz desenden 7'si mükemmel kümeleme önek eşleşmesidir. Kalan 8 tanesi, bölüm içi filtrelemeyle birlikte tek bölümlü okumalardır. En az bir bilinen öğeye sahip her sorgu, bir bölüm anahtarını etkiler.
|
||||
|
||||
Desen 16 (?,?,?,?) pratikte oluşmaz, çünkü koleksiyon her zaman belirtilir ve bu da onu desen 12'ye indirger.
|
||||
|
||||
### Yaygın Sorgu Örnekleri
|
||||
|
||||
**Bir varlık hakkında her şey:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice';
|
||||
```
|
||||
|
||||
**Bir varlık için tüm dış ilişkiler:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S';
|
||||
```
|
||||
|
||||
**Bir varlık için özel koşul:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows';
|
||||
```
|
||||
|
||||
**Bir varlık için etiket (belirli bir dil):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'http://www.w3.org/2000/01/rdf-schema#label'
|
||||
AND otype = 'L';
|
||||
```
|
||||
|
||||
Gerekirse, `lang = 'en'` uygulamasının tarafında filtreleme yapın.
|
||||
|
||||
**Sadece URI değerine sahip ilişkiler (varlıklar arası bağlantılar):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows' AND otype = 'U';
|
||||
```
|
||||
|
||||
**Ters sorgulama — bu varlığa neyin işaret ettiği:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Bob'
|
||||
AND role = 'O';
|
||||
```
|
||||
|
||||
## Etiket Çözümleme ve Önbellek Isıtma
|
||||
|
||||
Varlık odaklı modelin en önemli avantajlarından biri, **etiket çözümlemenin ücretsiz bir yan etki olmasıdır**.
|
||||
|
||||
Geleneksel çok tablolu modelde, etiketleri almak ayrı sorgu istekleri gerektirir: üçlüleri alın, sonuçlardaki varlık URI'larını belirleyin ve ardından her biri için `rdfs:label` alın. Bu N+1 deseni maliyetlidir.
|
||||
|
||||
Varlık odaklı modelde, bir varlığı sorgulamak, etiketleri, türleri ve diğer özellikleri de içeren **tüm** dörtlülerini döndürür. Uygulama sorgu sonuçlarını önbelleğe aldığında, etiketler herhangi bir şey onlardan istekte bulunmadan önce önceden ısıtılır.
|
||||
|
||||
İki kullanım rejimi, bunun pratikte iyi çalıştığını doğrulamaktadır:
|
||||
|
||||
**Kullanıcı arayüzüne yönelik sorgular**: doğal olarak küçük sonuç kümeleri, etiketler önemlidir. Varlık okumaları önbelleği önceden ısıtır.
|
||||
**AI/toplu sorgular**: büyük sonuç kümeleri ve sıkı sınırlar. Etiketler ya gereksizdir ya da önceden önbelleğe alınmış olan varlıkların yalnızca seçilmiş bir alt kümesi için gereklidir.
|
||||
|
||||
Çok büyük sonuç kümeleri (örneğin, 30.000 varlık) için etiketleri çözme konusundaki teorik endişe, hiçbir insan veya yapay zeka tüketicisinin o kadar çok etiketi faydalı bir şekilde işlemediği pratik gözlemiyle giderilir. Uygulama düzeyindeki sorgu sınırları, önbellek üzerindeki baskının yönetilebilir kalmasını sağlar.
|
||||
|
||||
## Geniş Bölümler ve Somutlaştırma
|
||||
|
||||
Somutlaştırma (RDF-star tarzı, ifadeler hakkında ifadeler), kaynak belge gibi merkez varlıkları oluşturur; bu belge, çıkarılan binlerce olguyu destekler. Bu, geniş bölümlere yol açabilir.
|
||||
|
||||
Hafifletici faktörler:
|
||||
|
||||
**Uygulama düzeyindeki sorgu sınırları**: tüm GraphRAG ve kullanıcı arayüzüne yönelik sorgular, geniş bölümlerin sıcak okuma yolunda asla tamamen taranmamasını sağlayan sıkı sınırlar uygular.
|
||||
**Cassandra, kısmi okumaları verimli bir şekilde işler**: erken durdurma ile bir küme sütunu taraması, büyük bölümlerde bile hızlıdır.
|
||||
**Koleksiyon silme** (sadece tüm bölümleri geçebilecek bir işlem), kabul edilebilir bir arka plan işlemidir.
|
||||
|
||||
## Koleksiyon Silme
|
||||
|
||||
API çağrısı tarafından tetiklenir, arka planda çalışır (eventually consistent).
|
||||
|
||||
1. Hedef koleksiyon için `quads_by_collection`'ı okuyun ve tüm dörtlüleri alın.
|
||||
2. Dörtlülerden benzersiz varlıkları çıkarın (s, p, o, d değerleri).
|
||||
3. Her benzersiz varlık için, `quads_by_entity`'dan ilgili bölümü silin.
|
||||
4. `quads_by_collection`'dan satırları silin.
|
||||
|
||||
`quads_by_collection` tablosu, tüm varlık bölümlerini tam tablo taraması olmadan bulmak için gereken dizini sağlar. Bölüm düzeyindeki silmeler verimlidir çünkü `(collection, entity)` bölüm anahtarıdır.
|
||||
|
||||
## Çok Tablolu Modelden Geçiş Yolu
|
||||
|
||||
Varlık odaklı model, geçiş sırasında mevcut çok tablolu modelle birlikte var olabilir:
|
||||
|
||||
1. `quads_by_entity` ve `quads_by_collection` tablolarını mevcut tablolara ek olarak dağıtın.
|
||||
2. Yeni dörtlüleri hem eski hem de yeni tablolara çift yazın.
|
||||
3. Mevcut verileri yeni tablolara geri yükleyin.
|
||||
4. Okuma yollarını bir sorgu deseni bir seferinde geçirin.
|
||||
5. Tüm okumalar geçirildikten sonra eski tabloları devre dışı bırakın.
|
||||
|
||||
## Özet
|
||||
|
||||
| Yön | Geleneksel (6 tablo) | Varlık odaklı (2 tablo) |
|
||||
|---|---|---|
|
||||
| Tablolar | 7+ | 2 |
|
||||
| Dörtlü başına yazma | 6+ | 5 (4 veri + 1 manifest) |
|
||||
| Etiket çözümleme | Ayrı sorgu istekleri | Önbellek ısıtma yoluyla ücretsiz |
|
||||
| Sorgu desenleri | 6 tabloda 16 | 1 tabloda 16 |
|
||||
| Şema karmaşıklığı | Yüksek | Düşük |
|
||||
| İşletimsel yük | Ayarlanması/onarılması gereken 6 tablo | 1 veri tablosu |
|
||||
| Somutlaştırma desteği | Ek karmaşıklık | Doğal uyum |
|
||||
| Nesne türü filtreleme | Kullanılamaz | Yerel (o tür kümeleme yoluyla) |
|
||||
ÇIKTI SÖZLEŞMESİ (tam olarak aşağıdaki formatı takip etmelidir):
|
||||
269
docs/tech-specs/entity-centric-graph.zh-cn.md
Normal file
269
docs/tech-specs/entity-centric-graph.zh-cn.md
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
---
|
||||
layout: default
|
||||
title: "基于实体的知识图谱在 Cassandra 上的存储"
|
||||
parent: "Chinese (Beta)"
|
||||
---
|
||||
|
||||
# 基于实体的知识图谱在 Cassandra 上的存储
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## 概述
|
||||
|
||||
本文档描述了一种在 Apache Cassandra 上存储 RDF 风格知识图谱的存储模型。该模型采用一种**以实体为中心**的方法,其中每个实体都知道它参与的所有四元组以及它所扮演的角色。这用两个表替换了传统的多表 SPO 组合方法。
|
||||
|
||||
## 背景和动机
|
||||
|
||||
### 传统方法
|
||||
|
||||
在 Cassandra 上,标准的 RDF 四元组存储需要多个反规范化的表来覆盖查询模式,通常需要 6 个或更多的表,这些表代表主语、谓词、宾语和数据集 (SPOD) 的不同组合。每个四元组都会写入到每个表中,从而导致显著的写入放大、运维开销和模式复杂性。
|
||||
|
||||
此外,标签解析(用于实体的人类可读名称)需要单独的往返查询,这在 AI 和 GraphRAG 用例中尤其昂贵,因为标签对于 LLM 上下文至关重要。
|
||||
|
||||
### 以实体为中心的洞察
|
||||
|
||||
每个四元组 `(D, S, P, O)` 涉及最多 4 个实体。通过为每个实体参与四元组的记录创建一个行,我们保证**任何至少包含一个已知元素的查询都会命中分区键**。这使用单个数据表覆盖所有 16 种查询模式。
|
||||
|
||||
主要优点:
|
||||
|
||||
**2 个表**,而不是 7 个以上
|
||||
**每个四元组 4 次写入**,而不是 6 次以上
|
||||
**免费的标签解析**——实体的标签与其关系共存,从而自然地预热应用程序缓存
|
||||
**所有 16 种查询模式**都由单分区读取提供
|
||||
**更简单的操作**——只有一个数据表需要调整、压缩和修复
|
||||
|
||||
## 模式
|
||||
|
||||
### 表 1:quads_by_entity
|
||||
|
||||
主要数据表。每个实体都有一个分区,其中包含它参与的所有四元组。该名称反映了查询模式(按实体查找)。
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_entity (
|
||||
collection text, -- Collection/tenant scope (always specified)
|
||||
entity text, -- The entity this row is about
|
||||
role text, -- 'S', 'P', 'O', 'G' — how this entity participates
|
||||
p text, -- Predicate of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
s text, -- Subject of the quad
|
||||
o text, -- Object of the quad
|
||||
d text, -- Dataset/graph of the quad
|
||||
dtype text, -- XSD datatype (when otype = 'L'), e.g. 'xsd:string'
|
||||
lang text, -- Language tag (when otype = 'L'), e.g. 'en', 'fr'
|
||||
PRIMARY KEY ((collection, entity), role, p, otype, s, o, d, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
**分区键 (Partition key)**: `(collection, entity)` — 作用域限定在集合中,每个实体对应一个分区。
|
||||
|
||||
**聚类列顺序的理由 (Clustering column order rationale)**:
|
||||
|
||||
1. **role** — 大部分查询都以“这个实体是哪个主语/客体”开始。
|
||||
2. **p** — 下一个最常见的过滤条件,例如“给我所有 `knows` 关系”。
|
||||
3. **otype** — 允许根据 URI 值与字面值关系进行过滤。
|
||||
4. **s, o, d** — 剩余的列用于保证唯一性。
|
||||
5. **dtype, lang** — 区分具有相同值但不同类型元数据的字面值(例如,`"thing"` 与 `"thing"@en` 与 `"thing"^^xsd:string`)。
|
||||
|
||||
### 表 2: quads_by_collection
|
||||
|
||||
支持集合级别的查询和删除。提供属于某个集合的所有四元组的清单。命名方式反映了查询模式(按集合查找)。
|
||||
|
||||
```sql
|
||||
CREATE TABLE quads_by_collection (
|
||||
collection text,
|
||||
d text, -- Dataset/graph of the quad
|
||||
s text, -- Subject of the quad
|
||||
p text, -- Predicate of the quad
|
||||
o text, -- Object of the quad
|
||||
otype text, -- 'U' (URI), 'L' (literal), 'T' (triple/reification)
|
||||
dtype text, -- XSD datatype (when otype = 'L')
|
||||
lang text, -- Language tag (when otype = 'L')
|
||||
PRIMARY KEY (collection, d, s, p, o, otype, dtype, lang)
|
||||
);
|
||||
```
|
||||
|
||||
首先按照数据集进行聚类,从而可以在集合或数据集级别进行删除。 `otype`、`dtype` 和 `lang` 列包含在聚类键中,用于区分具有相同值但不同元数据类型的字面量——在 RDF 中,`"thing"`、`"thing"@en` 和 `"thing"^^xsd:string` 是语义上不同的值。
|
||||
|
||||
## 写入路径
|
||||
|
||||
对于每个在集合 `C` 中的四元组 `(D, S, P, O)`,需要向 `quads_by_entity` 写入 **4 行**,并向 `quads_by_collection` 写入 **1 行**。
|
||||
|
||||
### 示例
|
||||
|
||||
假设在集合 `tenant1` 中的四元组是:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: https://example.org/knows
|
||||
Object: https://example.org/Bob
|
||||
```
|
||||
|
||||
将 4 行写入到 `quads_by_entity`:
|
||||
|
||||
| collection | entity | role | p | otype | s | o | d |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | G | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Alice | S | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/knows | P | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
| tenant1 | https://example.org/Bob | O | https://example.org/knows | U | https://example.org/Alice | https://example.org/Bob | https://example.org/graph1 |
|
||||
|
||||
将 1 行写入到 `quads_by_collection`:
|
||||
|
||||
| collection | d | s | p | o | otype | dtype | lang |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tenant1 | https://example.org/graph1 | https://example.org/Alice | https://example.org/knows | https://example.org/Bob | U | | |
|
||||
|
||||
### 示例
|
||||
|
||||
对于一个标签三元组:
|
||||
|
||||
```
|
||||
Dataset: https://example.org/graph1
|
||||
Subject: https://example.org/Alice
|
||||
Predicate: http://www.w3.org/2000/01/rdf-schema#label
|
||||
Object: "Alice Smith" (lang: en)
|
||||
```
|
||||
|
||||
`otype` 是 `'L'`,`dtype` 是 `'xsd:string'`,`lang` 是 `'en'`。 原始值 `"Alice Smith"` 存储在 `o` 中。 `quads_by_entity` 中只需要 3 行,因为没有为原始值作为实体的行,因为原始值不是可以独立查询的实体。
|
||||
|
||||
## 查询模式
|
||||
|
||||
### 所有 16 种 DSPO 模式
|
||||
|
||||
在下表中,“完美前缀”表示查询使用聚类列的连续前缀。“分区扫描 + 过滤”表示 Cassandra 读取一个分区的一部分并在内存中进行过滤,这仍然有效,但不是纯粹的前缀匹配。
|
||||
|
||||
| # | 已知 | 查找实体 | 聚类前缀 | 效率 |
|
||||
|---|---|---|---|---|
|
||||
| 1 | D,S,P,O | entity=S, role='S', p=P | 完全匹配 | 完美前缀 |
|
||||
| 2 | D,S,P,? | entity=S, role='S', p=P | 在 D 上过滤 | 分区扫描 + 过滤 |
|
||||
| 3 | D,S,?,O | entity=S, role='S' | 在 D, O 上过滤 | 分区扫描 + 过滤 |
|
||||
| 4 | D,?,P,O | entity=O, role='O', p=P | 在 D 上过滤 | 分区扫描 + 过滤 |
|
||||
| 5 | ?,S,P,O | entity=S, role='S', p=P | 在 O 上过滤 | 分区扫描 + 过滤 |
|
||||
| 6 | D,S,?,? | entity=S, role='S' | 在 D 上过滤 | 分区扫描 + 过滤 |
|
||||
| 7 | D,?,P,? | entity=P, role='P' | 在 D 上过滤 | 分区扫描 + 过滤 |
|
||||
| 8 | D,?,?,O | entity=O, role='O' | 在 D 上过滤 | 分区扫描 + 过滤 |
|
||||
| 9 | ?,S,P,? | entity=S, role='S', p=P | — | **完美前缀** |
|
||||
| 10 | ?,S,?,O | entity=S, role='S' | 在 O 上过滤 | 分区扫描 + 过滤 |
|
||||
| 11 | ?,?,P,O | entity=O, role='O', p=P | — | **完美前缀** |
|
||||
| 12 | D,?,?,? | entity=D, role='G' | — | **完美前缀** |
|
||||
| 13 | ?,S,?,? | entity=S, role='S' | — | **完美前缀** |
|
||||
| 14 | ?,?,P,? | entity=P, role='P' | — | **完美前缀** |
|
||||
| 15 | ?,?,?,O | entity=O, role='O' | — | **完美前缀** |
|
||||
| 16 | ?,?,?,? | — | 全扫描 | 仅探索 |
|
||||
|
||||
**关键结果:** 15 种非平凡模式中有 7 种是完美的聚类前缀匹配。 剩下的 8 种是单分区读取,并在分区内进行过滤。 包含至少一个已知元素的每个查询都会命中分区键。
|
||||
|
||||
模式 16 (?,?,?,?) 在实践中不会出现,因为集合始终是指定的,这将其简化为模式 12。
|
||||
|
||||
### 常见查询示例
|
||||
|
||||
**关于一个实体的所有信息:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice';
|
||||
```
|
||||
|
||||
**实体的所有出方向关系:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S';
|
||||
```
|
||||
|
||||
**特定实体谓词:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows';
|
||||
```
|
||||
|
||||
**实体标签(特定语言):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'http://www.w3.org/2000/01/rdf-schema#label'
|
||||
AND otype = 'L';
|
||||
```
|
||||
|
||||
然后,如果需要,可以在应用程序端通过 `lang = 'en'` 进行过滤。
|
||||
|
||||
**仅限 URI 值的关系(实体到实体的链接):**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Alice'
|
||||
AND role = 'S' AND p = 'https://example.org/knows' AND otype = 'U';
|
||||
```
|
||||
|
||||
**反向查找 — 指向此实体的对象:**
|
||||
|
||||
```sql
|
||||
SELECT * FROM quads_by_entity
|
||||
WHERE collection = 'tenant1' AND entity = 'https://example.org/Bob'
|
||||
AND role = 'O';
|
||||
```
|
||||
|
||||
## 标签解析和缓存预热
|
||||
|
||||
实体中心模型最显著的优势之一是,**标签解析成为一个免费的副作用**。
|
||||
|
||||
在传统的基于多表的模型中,获取标签需要单独的轮询查询:检索三元组,识别结果中的实体 URI,然后为每个 URI 获取 `rdfs:label`。 这种 N+1 模式非常昂贵。
|
||||
|
||||
在实体中心模型中,查询一个实体会返回其**所有**四元组,包括其标签、类型和其他属性。 当应用程序缓存查询结果时,标签会在任何客户端请求之前被预热。
|
||||
|
||||
两种使用模式证实了这在实践中效果良好:
|
||||
|
||||
**面向用户的查询**:结果集通常很小,标签至关重要。 实体读取会预热缓存。
|
||||
**AI/批量查询**:结果集很大,但有严格的限制。 标签要么是不必要的,要么只需要用于已缓存的实体子集。
|
||||
|
||||
解决大型结果集(例如 30,000 个实体)的标签的理论问题,可以通过实际观察来缓解,即没有人类或 AI 消费者能够有效地处理如此多的标签。 应用程序级别的查询限制可确保缓存压力保持在可管理范围内。
|
||||
|
||||
## 宽分区和重构
|
||||
|
||||
重构(RDF-star 风格的关于语句的语句)会创建中心实体,例如,一个源文档支持数千个提取的事实。 这可能会导致宽分区。
|
||||
|
||||
缓解因素:
|
||||
|
||||
**应用程序级别的查询限制**:所有 GraphRAG 和面向用户的查询都强制执行严格的限制,因此宽分区永远不会在热读取路径上被完全扫描。
|
||||
**Cassandra 可以高效地执行部分读取**:即使在大型分区上,具有早期停止的聚类列扫描也是快速的。
|
||||
**集合删除**(唯一可能遍历整个分区的操作)是一个可接受的后台过程。
|
||||
|
||||
## 集合删除
|
||||
|
||||
由 API 调用触发,在后台运行(最终一致)。
|
||||
|
||||
1. 读取 `quads_by_collection` 以获取目标集合的所有四元组
|
||||
2. 从四元组中提取唯一的实体(s、p、o、d 值)
|
||||
3. 对于每个唯一的实体,从 `quads_by_entity` 中删除该分区
|
||||
4. 从 `quads_by_collection` 中删除行
|
||||
|
||||
`quads_by_collection` 表提供了用于定位所有实体分区而无需进行全表扫描所需的索引。 由于 `(collection, entity)` 是分区键,因此分区级别的删除是高效的。
|
||||
|
||||
## 从多表模型迁移的路径
|
||||
|
||||
在迁移过程中,实体中心模型可以与现有的多表模型共存:
|
||||
|
||||
1. 将 `quads_by_entity` 和 `quads_by_collection` 表与现有表一起部署
|
||||
2. 同时将新的四元组写入旧表和新表
|
||||
3. 将现有数据回填到新表中
|
||||
4. 每次迁移一种查询模式
|
||||
5. 在迁移所有读取路径后,停用旧表
|
||||
|
||||
## 总结
|
||||
|
||||
| 方面 | 传统 (6 个表) | 实体中心 (2 个表) |
|
||||
|---|---|---|
|
||||
| 表 | 7+ | 2 |
|
||||
| 每个四元组的写入次数 | 6+ | 5 (4 个数据 + 1 个清单) |
|
||||
| 标签解析 | 单独的轮询 | 通过缓存预热免费 |
|
||||
| 查询模式 | 6 个表中的 16 种 | 1 个表中的 16 种 |
|
||||
| 模式复杂性 | 高 | 低 |
|
||||
| 运维开销 | 6 个表需要调整/修复 | 1 个数据表 |
|
||||
| 重构支持 | 额外的复杂性 | 完美契合 |
|
||||
| 对象类型过滤 | 不可用 | 原生 (通过 otype 聚类) |
|
||||
输出合同(必须严格遵守以下格式):
|
||||
178
docs/tech-specs/explainability-cli.ar.md
Normal file
178
docs/tech-specs/explainability-cli.ar.md
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
---
|
||||
layout: default
|
||||
title: "مواصفات سطر الأوامر لـ 'Explainability CLI'"
|
||||
parent: "Arabic (Beta)"
|
||||
---
|
||||
|
||||
# مواصفات سطر الأوامر لـ "Explainability CLI"
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## الحالة
|
||||
|
||||
مُقترح
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
تصف هذه المواصفة أدوات سطر الأوامر لتصحيح الأخطاء واستكشاف بيانات الشرح في TrustGraph. تسمح هذه الأدوات للمستخدمين بتتبع كيفية استخلاص الإجابات وتصحيح سلسلة الأصل من الحواف إلى المستندات المصدر.
|
||||
|
||||
ثلاث أدوات سطر أوامر:
|
||||
|
||||
1. **`tg-show-document-hierarchy`** - عرض تسلسل المستند → الصفحة → الجزء → الحافة
|
||||
2. **`tg-list-explain-traces`** - سرد جميع جلسات GraphRAG مع الأسئلة
|
||||
3. **`tg-show-explain-trace`** - عرض مسار الشرح الكامل لجلسة
|
||||
|
||||
## الأهداف
|
||||
|
||||
- **تصحيح الأخطاء**: تمكين المطورين من فحص نتائج معالجة المستندات
|
||||
- **قابلية التدقيق**: تتبع أي حقيقة مستخرجة إلى مستندها المصدر
|
||||
- **الشفافية**: إظهار بالضبط كيف اشتق GraphRAG إجابة
|
||||
- **سهولة الاستخدام**: واجهة سطر أوامر بسيطة مع قيم افتراضية معقولة
|
||||
|
||||
## الخلفية
|
||||
|
||||
يحتوي TrustGraph على نظامين لتعقب:
|
||||
|
||||
1. **تعقب وقت الاستخراج** (انظر `extraction-time-provenance.md`): يسجل علاقات المستند → الصفحة → الجزء → الحافة أثناء الاستيعاب. يتم تخزينها في رسم بياني يسمى `urn:graph:source` باستخدام `prov:wasDerivedFrom`.
|
||||
|
||||
2. **شرح قابل للتفسير في وقت الاستعلام** (انظر `query-time-explainability.md`): يسجل سلسلة السؤال → الاستكشاف → التركيز → التجميع أثناء استعلامات GraphRAG. يتم تخزينها في رسم بياني يسمى `urn:graph:retrieval`.
|
||||
|
||||
القيود الحالية:
|
||||
- لا توجد طريقة سهلة لتصور تسلسل المستند بعد المعالجة
|
||||
- يجب الاستعلام يدويًا عن المثلثات لعرض بيانات الشرح
|
||||
- لا يوجد عرض موحد لجلسة GraphRAG
|
||||
|
||||
## التصميم الفني
|
||||
|
||||
### الأداة 1: tg-show-document-hierarchy
|
||||
|
||||
**الغرض**: إعطاء معرف المستند، والتحرك وعرض جميع الكيانات المشتقة.
|
||||
|
||||
**الاستخدام**:
|
||||
```bash
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:abc123"
|
||||
tg-show-document-hierarchy --show-content --max-content 500 "urn:trustgraph:doc:abc123"
|
||||
```
|
||||
|
||||
**الوسائط**:
|
||||
| الوسيط | الوصف |
|
||||
|---|---|
|
||||
| `document_id` | URI للمستند (موضعي) |
|
||||
| `-u/--api-url` | عنوان URL لـ Gateway |
|
||||
| `-t/--token` | رمز المصادقة |
|
||||
| `-U/--user` | معرف المستخدم |
|
||||
| `-C/--collection` | المجموعة |
|
||||
| `--show-content` | تضم محتوى Blob/المستند |
|
||||
| `--max-content` | أقصى عدد من الأحرف في Blob (افتراضي: 200) |
|
||||
| `--format` | الإخراج: `tree` (افتراضي)، `json` |
|
||||
|
||||
**التنفيذ**:
|
||||
1. استعلام عن المثلثات: `?child prov:wasDerivedFrom <document_id>` في `urn:graph:source`
|
||||
2. استعلام بشكل متكرر عن الأطفال لكل نتيجة
|
||||
3. بناء بنية الشجرة: المستند → الصفحات → الأجزاء
|
||||
4. إذا كان `--show-content`، فقم باسترداد المحتوى من واجهة برمجة التطبيقات الخاصة بالمكتبة
|
||||
5. عرض كشجرة مسطحة أو JSON
|
||||
|
||||
**مثال على الإخراج**:
|
||||
```
|
||||
المستند: urn:trustgraph:doc:abc123
|
||||
العنوان: "Sample PDF"
|
||||
النوع: application/pdf
|
||||
|
||||
└── الصفحة 1: urn:trustgraph:doc:abc123/p1
|
||||
├── الجزء 0: urn:trustgraph:doc:abc123/p1/c0
|
||||
المحتوى: "The quick brown fox..." [مقتطف]
|
||||
└── الجزء 1: urn:trustgraph:doc:abc123/p1/c1
|
||||
المحتوى: "Machine learning is..." [مقتطف]
|
||||
```
|
||||
|
||||
### الأداة 2: tg-list-explain-traces
|
||||
|
||||
**الغرض**: سرد جميع جلسات GraphRAG (الأسئلة) في مجموعة.
|
||||
|
||||
**الاستخدام**:
|
||||
```bash
|
||||
tg-list-explain-traces
|
||||
tg-list-explain-traces --limit 20 --format json
|
||||
```
|
||||
|
||||
**الوسائط**:
|
||||
| الوسيط | الوصف |
|
||||
|---|---|
|
||||
| `-u/--api-url` | عنوان URL لـ Gateway |
|
||||
| `-t/--token` | رمز المصادقة |
|
||||
| `-U/--user` | معرف المستخدم |
|
||||
| `-C/--collection` | المجموعة |
|
||||
| `--limit` | أقصى عدد من النتائج (افتراضي: 50) |
|
||||
| `--format` | الإخراج: `table` (افتراضي)، `json` |
|
||||
|
||||
**التنفيذ**:
|
||||
1. استعلام: `?session tg:query ?text` في `urn:graph:retrieval`
|
||||
2. استعلام عن الطوابع الزمنية: `?session prov:startedAtTime ?time`
|
||||
3. عرض كجدول
|
||||
|
||||
**مثال على الإخراج**:
|
||||
```
|
||||
معرف الجلسة | السؤال | الوقت
|
||||
----------------------------------------------|--------------------------------|---------------------
|
||||
urn:trustgraph:question:abc123 | What was the War on Terror? | 2024-01-15 10:30:00
|
||||
urn:trustgraph:question:def456 | Who founded OpenAI? | 2024-01-15 09:15:00
|
||||
```
|
||||
|
||||
### الأداة 3: tg-show-explain-trace
|
||||
|
||||
**الغرض**: عرض مسار الشرح الكامل لجلسة GraphRAG.
|
||||
|
||||
**الاستخدام**:
|
||||
```bash
|
||||
tg-show-explain-trace "urn:trustgraph:question:abc123"
|
||||
tg-show-explain-trace --max-answer 1000 --show-provenance "urn:trustgraph:question:abc123"
|
||||
```
|
||||
|
||||
**الوسائط**:
|
||||
| الوسيط | الوصف |
|
||||
|---|---|
|
||||
| `question_id` | معرف السؤال (موضعي) |
|
||||
| `-u/--api-url` | عنوان URL لـ Gateway |
|
||||
| `-t/--token` | رمز المصادقة |
|
||||
| `-U/--user` | معرف المستخدم |
|
||||
| `-C/--collection` | المجموعة |
|
||||
| `--max-answer` | أقصى عدد من الأحرف للإجابة (افتراضي: 500) |
|
||||
| `--show-provenance` | تتبع الحواف إلى المستندات المصدر |
|
||||
| `--format` | الإخراج: `text` (افتراضي)، `json` |
|
||||
|
||||
**التنفيذ**:
|
||||
1. الحصول على نص السؤال من البُعد `tg:query`
|
||||
2. العثور على الاستكشاف: `?exp prov:wasGeneratedBy <question_id>`
|
||||
3. العثور على التركيز: `?focus prov:wasDerivedFrom <exploration_id>`
|
||||
4. الحصول على الحواف المحددة: `<focus_id> tg:selectedEdge ?edge`
|
||||
5. لكل حافة، الحصول على `tg:edge` (سلسلة RDF) و `tg:reasoning`
|
||||
6. العثور على التجميع: `?synth prov:wasDerivedFrom <focus_id>`
|
||||
7. الحصول على الإجابة من `tg:document` عبر واجهة برمجة التطبيقات
|
||||
8. إذا كان `--show-provenance`، فقم بتتبع الحواف إلى المستندات المصدر
|
||||
|
||||
**مثال على الإخراج**:
|
||||
```
|
||||
=== جلسة GraphRAG: urn:trustgraph:question:abc123 ===
|
||||
|
||||
السؤال: What was the War on Terror?
|
||||
الوقت: 2024-01-15 10:30:00
|
||||
|
||||
الإجابة: [إجابة]
|
||||
|
||||
مسار الشرح:
|
||||
- السؤال: What was the War on Terror?
|
||||
- استخراج: [ملف]
|
||||
- تجميع: [إطار عمل]
|
||||
- استجابة: [إجابة]
|
||||
- السؤال: What was the War on Terror?
|
||||
- استخراج: [ملف]
|
||||
- تجميع: [إطار عمل]
|
||||
- استجابة: [إجابة]
|
||||
```
|
||||
|
||||
## المراجع
|
||||
|
||||
- شرح قابل للتفسير: `docs/tech-specs/query-time-explainability.md`
|
||||
- تتبع وقت الاستخراج: `docs/tech-specs/extraction-time-provenance.md`
|
||||
- مثال سطر الأوامر: `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py`
|
||||
188
docs/tech-specs/explainability-cli.es.md
Normal file
188
docs/tech-specs/explainability-cli.es.md
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificación Técnica de la CLI para Explicabilidad"
|
||||
parent: "Spanish (Beta)"
|
||||
---
|
||||
|
||||
# Especificación Técnica de la CLI para Explicabilidad
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Estado
|
||||
|
||||
Borrador
|
||||
|
||||
## Visión General
|
||||
|
||||
Esta especificación describe las herramientas de CLI para depurar y explorar datos de explicabilidad en TrustGraph. Estas herramientas permiten a los usuarios rastrear cómo se derivaron las respuestas y depurar la cadena de origen desde los bordes hasta los documentos fuente.
|
||||
|
||||
Tres herramientas de CLI:
|
||||
|
||||
1. **`tg-show-document-hierarchy`** - Muestra la jerarquía documento → página → fragmento → borde
|
||||
2. **`tg-list-explain-traces`** - Lista todas las sesiones GraphRAG con preguntas
|
||||
3. **`tg-show-explain-trace`** - Muestra la trazabilidad completa de explicabilidad para una sesión
|
||||
|
||||
## Objetivos
|
||||
|
||||
- **Depuración**: Permitir a los desarrolladores inspeccionar los resultados del procesamiento de documentos.
|
||||
- **Auditabilidad**: Rastrear cualquier hecho extraído hasta su documento fuente.
|
||||
- **Transparencia**: Mostrar exactamente cómo GraphRAG derivó una respuesta.
|
||||
- **Usabilidad**: Interfaz CLI sencilla con valores predeterminados apropiados.
|
||||
|
||||
## Antecedentes
|
||||
|
||||
TrustGraph tiene dos sistemas de origen:
|
||||
|
||||
1. **Origen en tiempo de extracción** (ver `extraction-time-provenance.md`): Registra las relaciones documento → página → fragmento → borde durante la ingestión. Almacenado en el gráfico llamado `urn:graph:source` utilizando `prov:wasDerivedFrom`.
|
||||
|
||||
2. **Explicabilidad en tiempo de consulta** (ver `query-time-explainability.md`): Registra la cadena de pregunta → exploración → enfoque → síntesis durante las consultas GraphRAG. Almacenado en el gráfico llamado `urn:graph:retrieval`.
|
||||
|
||||
Limitaciones actuales:
|
||||
|
||||
- No hay una manera fácil de visualizar la jerarquía del documento después del procesamiento.
|
||||
- Se deben consultar manualmente los triples para ver los datos de explicabilidad.
|
||||
- No hay una vista consolidada de una sesión GraphRAG.
|
||||
|
||||
## Diseño Técnico
|
||||
|
||||
### Herramienta 1: `tg-show-document-hierarchy`
|
||||
|
||||
**Propósito**: Dado un ID de documento, recorrer y mostrar todas las entidades derivadas.
|
||||
|
||||
**Uso**:
|
||||
```bash
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:abc123"
|
||||
tg-show-document-hierarchy --show-content --max-content 500 "urn:trustgraph:doc:abc123"
|
||||
```
|
||||
|
||||
**Argumentos**:
|
||||
| Arg | Descripción |
|
||||
|---|---|
|
||||
| `document_id` | URI del documento (posicional) |
|
||||
| `-u/--api-url` | URL del gateway (por defecto: `$TRUSTGRAPH_URL`) |
|
||||
| `-t/--token` | Token de autenticación (por defecto: `$TRUSTGRAPH_TOKEN`) |
|
||||
| `-U/--user` | ID de usuario (por defecto: `trustgraph`) |
|
||||
| `-C/--collection` | Colección (por defecto: `default`) |
|
||||
| `--show-content` | Incluir el contenido del blob/documento |
|
||||
| `--max-content` | Máx. caracteres por blob (por defecto: 200) |
|
||||
| `--format` | Salida: `tree` (por defecto), `json` |
|
||||
|
||||
**Implementación**:
|
||||
1. Consultar triples: `?child prov:wasDerivedFrom <document_id>` en `urn:graph:source`
|
||||
2. Consultar recursivamente los hijos de cada resultado
|
||||
3. Construir la estructura del árbol: Documento → Páginas → Fragmentos
|
||||
4. Si `--show-content`, recuperar el contenido de la API del bibliotecario
|
||||
5. Mostrar como árbol anidado o JSON
|
||||
|
||||
**Ejemplo de Salida**:
|
||||
```
|
||||
Document: urn:trustgraph:doc:abc123
|
||||
Título: "Sample PDF"
|
||||
Tipo: application/pdf
|
||||
|
||||
└── Página 1: urn:trustgraph:doc:abc123/p1
|
||||
├── Fragmento 0: urn:trustgraph:doc:abc123/p1/c0
|
||||
Contenido: "The quick brown fox..." [truncado]
|
||||
└── Fragmento 1: urn:trustgraph:doc:abc123/p1/c1
|
||||
Contenido: "Machine learning is..." [truncado]
|
||||
```
|
||||
|
||||
### Herramienta 2: `tg-list-explain-traces`
|
||||
|
||||
**Propósito**: Listar todas las sesiones GraphRAG (preguntas) en una colección.
|
||||
|
||||
**Uso**:
|
||||
```bash
|
||||
tg-list-explain-traces
|
||||
tg-list-explain-traces --limit 20 --format json
|
||||
```
|
||||
|
||||
**Argumentos**:
|
||||
| Arg | Descripción |
|
||||
|---|---|
|
||||
| `-u/--api-url` | URL del gateway |
|
||||
| `-t/--token` | Token de autenticación |
|
||||
| `-U/--user` | ID de usuario |
|
||||
| `-C/--collection` | Colección |
|
||||
| `--limit` | Máx. resultados (por defecto: 50) |
|
||||
| `--format` | Salida: `table` (por defecto), `json` |
|
||||
|
||||
**Implementación**:
|
||||
1. Consultar: `?session tg:query ?text` en `urn:graph:retrieval`
|
||||
2. Consultar los tiempos: `?session prov:startedAtTime ?time`
|
||||
3. Mostrar como tabla
|
||||
|
||||
**Ejemplo de Salida**:
|
||||
```
|
||||
Session ID | Pregunta | Tiempo
|
||||
----------------------------------------------|--------------------------------|---------------------
|
||||
urn:trustgraph:question:abc123 | ¿Cuál fue la Guerra Fría? | 2024-01-15 10:30:00
|
||||
urn:trustgraph:question:def456 | ¿Quién fundó la NASA? | 2024-01-15 09:15:00
|
||||
```
|
||||
|
||||
### Herramienta 3: `tg-show-explain-trace`
|
||||
|
||||
**Propósito**: Mostrar la trazabilidad completa de explicabilidad para una sesión GraphRAG.
|
||||
|
||||
**Uso**:
|
||||
```bash
|
||||
tg-show-explain-trace "urn:trustgraph:question:abc123"
|
||||
tg-show-explain-trace --max-answer 1000 --show-provenance "urn:trustgraph:question:abc123"
|
||||
```
|
||||
|
||||
**Argumentos**:
|
||||
| Arg | Descripción |
|
||||
|---|---|
|
||||
| `question_id` | URI de la pregunta (posicional) |
|
||||
| `-u/--api-url` | URL del gateway |
|
||||
| `-t/--token` | Token de autenticación |
|
||||
| `-U/--user` | ID de usuario |
|
||||
| `-C/--collection` | Colección |
|
||||
| `--max-answer` | Máx. caracteres para la respuesta (por defecto: 500) |
|
||||
| `--show-provenance` | Rastrear los bordes hasta los documentos fuente |
|
||||
| `--format` | Salida: `text` (por defecto), `json` |
|
||||
|
||||
**Implementación**:
|
||||
1. Obtener el texto de la pregunta del predicado `tg:query`
|
||||
2. Encontrar la exploración: `?exp prov:wasGeneratedBy <question_id>`
|
||||
3. Encontrar el enfoque: `?focus prov:wasDerivedFrom <exploration_id>`
|
||||
4. Obtener los bordes seleccionados: `<focus_id> tg:selectedEdge ?edge`
|
||||
5. Para cada borde, obtener `tg:edge` (triple acotado) y `tg:reasoning`
|
||||
6. Encontrar la síntesis: `?synth prov:wasDerivedFrom <focus_id>`
|
||||
7. Obtener la respuesta del documento a través de la API del bibliotecario
|
||||
8. Si `--show-provenance`, rastrear los bordes hasta los documentos fuente
|
||||
|
||||
**Ejemplo de Salida**:
|
||||
```
|
||||
=== Sesión GraphRAG: urn:trustgraph:question:abc123 ===
|
||||
|
||||
Pregunta: ¿Cuál fue la Guerra Fría?
|
||||
Tiempo: 2024-01-15 10:30:00
|
||||
|
||||
--- Exploración ---
|
||||
Se recuperaron 50 bordes de la gráfica de conocimiento
|
||||
|
||||
--- Enfoque (Selección de Bordes) ---
|
||||
Se seleccionaron 12 bordes:
|
||||
|
||||
1. "The Cold War"
|
||||
2. "Yuri Andropov"
|
||||
3. "Khrushchev"
|
||||
4. "NATO"
|
||||
5. "Warsaw Pact"
|
||||
6. "Berlin Wall"
|
||||
7. "Cuban Missile Crisis"
|
||||
8. "Detente"
|
||||
9. "Détente"
|
||||
10. "Joseph Stalin"
|
||||
11. "Nikita Khrushchev"
|
||||
12. "US-Soviet Relations"
|
||||
|
||||
--- Trazabilidad ---
|
||||
```
|
||||
|
||||
## Referencias
|
||||
|
||||
- CLI de explicabilidad: `docs/tech-specs/query-time-explainability.md`
|
||||
- Origen en tiempo de extracción: `docs/tech-specs/extraction-time-provenance.md`
|
||||
- Ejemplo de CLI: `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py`
|
||||
228
docs/tech-specs/explainability-cli.he.md
Normal file
228
docs/tech-specs/explainability-cli.he.md
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
---
|
||||
layout: default
|
||||
title: "מפרט טכני של כלי שורת הפקודה (CLI) להסברתיות"
|
||||
parent: "Hebrew (Beta)"
|
||||
---
|
||||
|
||||
# מפרט טכני של כלי שורת הפקודה (CLI) להסברתיות
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## סטטוס
|
||||
|
||||
טיוטה
|
||||
|
||||
## סקירה כללית
|
||||
|
||||
מפרט זה מתאר כלי שורת פקודה (CLI) לניפוי באגים ובדיקת נתוני הסברתיות ב-TrustGraph. כלים אלה מאפשרים למשתמשים לעקוב אחר אופן קבלת התשובות ולבצע ניפוי באגים בשרשרת המקור, החל מצמתים ועד למסמכים מקוריים.
|
||||
|
||||
שלושה כלים של שורת פקודה:
|
||||
|
||||
1. **`tg-show-document-hierarchy`** - הצגת היררכיה של מסמך → עמוד → מקטע → צומת
|
||||
2. **`tg-list-explain-traces`** - הצגת רשימה של כל הסשנים של GraphRAG עם שאלות
|
||||
3. **`tg-show-explain-trace`** - הצגת מעקב הסברתיות מלא עבור סשן
|
||||
|
||||
## מטרות
|
||||
|
||||
**ניפוי באגים**: לאפשר למפתחים לבדוק את תוצאות עיבוד המסמכים
|
||||
**ביקורת**: לעקוב אחר כל עובדה שחולצה בחזרה למסמך המקור שלה
|
||||
**שקיפות**: להציג בדיוק כיצד GraphRAG הגיע לתשובה
|
||||
**שימושיות**: ממשק שורת פקודה פשוט עם הגדרות ברירת מחדל הגיוניות
|
||||
|
||||
## רקע
|
||||
|
||||
ל-TrustGraph יש שתי מערכות מעקב מקור:
|
||||
|
||||
1. **מעקב מקור בזמן חילוץ** (ראה `extraction-time-provenance.md`): מתעד את היחסים בין מסמך → עמוד → מקטע → צומת במהלך הטעינה. מאוחסן בגרף בשם `urn:graph:source` באמצעות `prov:wasDerivedFrom`.
|
||||
|
||||
2. **הסברתיות בזמן שאילתה** (ראה `query-time-explainability.md`): מתעד את שרשרת השאלות → חקירה → מיקוד → סינתזה במהלך שאילתות GraphRAG. מאוחסן בגרף בשם `urn:graph:retrieval`.
|
||||
|
||||
מגבלות נוכחיות:
|
||||
אין דרך קלה להציג את היררכיית המסמכים לאחר העיבוד
|
||||
יש לבצע שאילתות ידניות על משולשים כדי לראות נתוני הסברתיות
|
||||
אין תצוגה מאוחדת של סשן GraphRAG
|
||||
|
||||
## עיצוב טכני
|
||||
|
||||
### כלי 1: tg-show-document-hierarchy
|
||||
|
||||
**מטרה**: בהינתן מזהה מסמך, לעבור ולציין את כל הישויות הנגזרות.
|
||||
|
||||
**שימוש**:
|
||||
```bash
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:abc123"
|
||||
tg-show-document-hierarchy --show-content --max-content 500 "urn:trustgraph:doc:abc123"
|
||||
```
|
||||
|
||||
**ארגומנטים**:
|
||||
| Arg | תיאור |
|
||||
|-----|-------------|
|
||||
| `document_id` | כתובת URI של המסמך (מיקום) |
|
||||
| `-u/--api-url` | כתובת URL של ה-Gateway (ברירת מחדל: `$TRUSTGRAPH_URL`) |
|
||||
| `-t/--token` | טוקן אימות (ברירת מחדל: `$TRUSTGRAPH_TOKEN`) |
|
||||
| `-U/--user` | מזהה משתמש (ברירת מחדל: `trustgraph`) |
|
||||
| `-C/--collection` | אוסף (ברירת מחדל: `default`) |
|
||||
| `--show-content` | לכלול תוכן של קבצים/מסמכים |
|
||||
| `--max-content` | מספר תווים מקסימלי לכל קובץ (ברירת מחדל: 200) |
|
||||
| `--format` | פלט: `tree` (ברירת מחדל), `json` |
|
||||
|
||||
**יישום**:
|
||||
1. שאילת משולשות: `?child prov:wasDerivedFrom <document_id>` ב-`urn:graph:source`
|
||||
2. שאילת באופן רקורסיבי את הילדים של כל תוצאה
|
||||
3. בניית מבנה עץ: מסמך → עמודים → חלקים
|
||||
4. אם `--show-content`, שליפה של תוכן מ-API של הספרן
|
||||
5. הצגה כמבנה עץ עם הזחות או JSON
|
||||
|
||||
**דוגמה לפלט**:
|
||||
```
|
||||
Document: urn:trustgraph:doc:abc123
|
||||
Title: "Sample PDF"
|
||||
Type: application/pdf
|
||||
|
||||
└── Page 1: urn:trustgraph:doc:abc123/p1
|
||||
├── Chunk 0: urn:trustgraph:doc:abc123/p1/c0
|
||||
│ Content: "The quick brown fox..." [truncated]
|
||||
└── Chunk 1: urn:trustgraph:doc:abc123/p1/c1
|
||||
Content: "Machine learning is..." [truncated]
|
||||
```
|
||||
|
||||
### כלי 2: tg-list-explain-traces
|
||||
|
||||
**מטרה**: הצגת כל הסשנים (שאלות) של GraphRAG באוסף.
|
||||
|
||||
**שימוש**:
|
||||
```bash
|
||||
tg-list-explain-traces
|
||||
tg-list-explain-traces --limit 20 --format json
|
||||
```
|
||||
|
||||
**ארגומנטים**:
|
||||
| Arg | תיאור |
|
||||
|-----|-------------|
|
||||
| `-u/--api-url` | כתובת URL של ה-Gateway |
|
||||
| `-t/--token` | טוקן אימות |
|
||||
| `-U/--user` | מזהה משתמש |
|
||||
| `-C/--collection` | אוסף |
|
||||
| `--limit` | מספר תוצאות מקסימלי (ברירת מחדל: 50) |
|
||||
| `--format` | פלט: `table` (ברירת מחדל), `json` |
|
||||
|
||||
**יישום**:
|
||||
1. שאילתה: `?session tg:query ?text` ב-`urn:graph:retrieval`
|
||||
2. שאילתת חותמות זמן: `?session prov:startedAtTime ?time`
|
||||
3. הצגה כטבלה
|
||||
|
||||
**דוגמה לפלט**:
|
||||
```
|
||||
Session ID | Question | Time
|
||||
----------------------------------------------|--------------------------------|---------------------
|
||||
urn:trustgraph:question:abc123 | What was the War on Terror? | 2024-01-15 10:30:00
|
||||
urn:trustgraph:question:def456 | Who founded OpenAI? | 2024-01-15 09:15:00
|
||||
```
|
||||
|
||||
### כלי 3: tg-show-explain-trace
|
||||
|
||||
**מטרה**: הצגת שרשרת ההסברים המלאה עבור סשן GraphRAG.
|
||||
|
||||
**שימוש**:
|
||||
```bash
|
||||
tg-show-explain-trace "urn:trustgraph:question:abc123"
|
||||
tg-show-explain-trace --max-answer 1000 --show-provenance "urn:trustgraph:question:abc123"
|
||||
```
|
||||
|
||||
**ארגומנטים**:
|
||||
| Arg | תיאור |
|
||||
|-----|-------------|
|
||||
| `question_id` | כתובת URI של שאלה (מיקום) |
|
||||
| `-u/--api-url` | כתובת URL של שער |
|
||||
| `-t/--token` | טוקן אימות |
|
||||
| `-U/--user` | מזהה משתמש |
|
||||
| `-C/--collection` | אוסף |
|
||||
| `--max-answer` | מספר תווים מקסימלי לתשובה (ברירת מחדל: 500) |
|
||||
| `--show-provenance` | לעקוב אחר קשרים למסמכים מקוריים |
|
||||
| `--format` | פלט: `text` (ברירת מחדל), `json` |
|
||||
|
||||
**יישום**:
|
||||
1. קבל את טקסט השאלה מ-`tg:query` (predicate)
|
||||
2. מצא חקירה: `?exp prov:wasGeneratedBy <question_id>`
|
||||
3. מצא מיקוד: `?focus prov:wasDerivedFrom <exploration_id>`
|
||||
4. קבל קשרים שנבחרו: `<focus_id> tg:selectedEdge ?edge`
|
||||
5. עבור כל קשר, קבל `tg:edge` (משולש מצוטט) ו-`tg:reasoning`
|
||||
6. מצא סינתזה: `?synth prov:wasDerivedFrom <focus_id>`
|
||||
7. קבל את התשובה מ-`tg:document` דרך הספרן |
|
||||
8. אם `--show-provenance`, עקוב אחר קשרים למסמכים מקוריים
|
||||
|
||||
**דוגמה לפלט**:
|
||||
```
|
||||
=== GraphRAG Session: urn:trustgraph:question:abc123 ===
|
||||
|
||||
Question: What was the War on Terror?
|
||||
Time: 2024-01-15 10:30:00
|
||||
|
||||
--- Exploration ---
|
||||
Retrieved 50 edges from knowledge graph
|
||||
|
||||
--- Focus (Edge Selection) ---
|
||||
Selected 12 edges:
|
||||
|
||||
1. (War on Terror, definition, "A military campaign...")
|
||||
Reasoning: Directly defines the subject of the query
|
||||
Source: chunk → page 2 → "Beyond the Vigilant State"
|
||||
|
||||
2. (Guantanamo Bay, part_of, War on Terror)
|
||||
Reasoning: Shows key component of the campaign
|
||||
|
||||
--- Synthesis ---
|
||||
Answer:
|
||||
The War on Terror was a military campaign initiated...
|
||||
[truncated at 500 chars]
|
||||
```
|
||||
|
||||
## קבצים ליצירה
|
||||
|
||||
| קובץ | מטרה |
|
||||
|------|---------|
|
||||
| `trustgraph-cli/trustgraph/cli/show_document_hierarchy.py` | כלי 1 |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | כלי 2 |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | כלי 3 |
|
||||
|
||||
## קבצים לשינוי
|
||||
|
||||
| קובץ | שינוי |
|
||||
|------|--------|
|
||||
| `trustgraph-cli/setup.py` | הוספת רשומות ל-console_scripts |
|
||||
|
||||
## הערות יישום
|
||||
|
||||
1. **בטיחות תוכן בינארי**: נסה לפענח UTF-8; אם נכשל, הצג `[Binary: {size} bytes]`
|
||||
2. **חיתוך**: שמור על `--max-content`/`--max-answer` עם מציין `[truncated]`
|
||||
3. **משולשות מצוטטות**: נתח פורמט RDF-star מ-predicate `tg:edge`
|
||||
4. **תבניות**: עקוב אחר תבניות CLI קיימות מ-`query_graph.py`
|
||||
|
||||
## שיקולי אבטחה
|
||||
|
||||
כל השאילתות מכבדות את גבולות המשתמש/אוסף
|
||||
אימות טוקן נתמך באמצעות `--token` או `$TRUSTGRAPH_TOKEN`
|
||||
|
||||
## אסטרטגיית בדיקה
|
||||
|
||||
אימות ידני עם נתוני דוגמה:
|
||||
```bash
|
||||
# Load a test document
|
||||
tg-load-pdf -f test.pdf -c test-collection
|
||||
|
||||
# Verify hierarchy
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:test"
|
||||
|
||||
# Run a GraphRAG query with explainability
|
||||
tg-invoke-graph-rag --explainable -q "Test question"
|
||||
|
||||
# List and inspect traces
|
||||
tg-list-explain-traces
|
||||
tg-show-explain-trace "urn:trustgraph:question:xxx"
|
||||
```
|
||||
|
||||
## הפניות
|
||||
|
||||
הסבר בזמן שאילתה: `docs/tech-specs/query-time-explainability.md`
|
||||
מקור בזמן חילוץ: `docs/tech-specs/extraction-time-provenance.md`
|
||||
דוגמה קיימת של שורת פקודה: `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py`
|
||||
228
docs/tech-specs/explainability-cli.hi.md
Normal file
228
docs/tech-specs/explainability-cli.hi.md
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
---
|
||||
layout: default
|
||||
title: "व्याख्यात्मकता CLI तकनीकी विनिर्देश"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# व्याख्यात्मकता CLI तकनीकी विनिर्देश
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## स्थिति
|
||||
|
||||
मसौदा
|
||||
|
||||
## अवलोकन
|
||||
|
||||
यह विनिर्देश ट्रस्टग्राफ में व्याख्यात्मकता डेटा को डिबग और एक्सप्लोर करने के लिए CLI टूल का वर्णन करता है। ये उपकरण उपयोगकर्ताओं को यह ट्रैक करने में सक्षम बनाते हैं कि उत्तर कैसे प्राप्त किए गए और किनारा से वापस स्रोत दस्तावेजों तक उत्पत्ति श्रृंखला को डिबग किया गया।
|
||||
|
||||
तीन CLI उपकरण:
|
||||
|
||||
1. **`tg-show-document-hierarchy`** - दस्तावेज़ → पृष्ठ → भाग → किनारा पदानुक्रम दिखाएं
|
||||
2. **`tg-list-explain-traces`** - सभी GraphRAG सत्रों को प्रश्नों के साथ सूचीबद्ध करें
|
||||
3. **`tg-show-explain-trace`** - एक सत्र के लिए पूर्ण व्याख्यात्मकता ट्रेस दिखाएं
|
||||
|
||||
## लक्ष्य
|
||||
|
||||
**डीबगिंग**: डेवलपर्स को दस्तावेज़ प्रसंस्करण परिणामों का निरीक्षण करने में सक्षम करें
|
||||
**लेखापरीक्षा**: किसी भी निकाले गए तथ्य को उसके स्रोत दस्तावेज़ तक ट्रैक करें
|
||||
**पारदर्शिता**: सटीक रूप से दिखाएं कि GraphRAG ने उत्तर कैसे प्राप्त किया
|
||||
**उपयोगिता**: समझदार डिफ़ॉल्ट के साथ सरल CLI इंटरफ़ेस
|
||||
|
||||
## पृष्ठभूमि
|
||||
|
||||
ट्रस्टग्राफ में दो उत्पत्ति प्रणालियाँ हैं:
|
||||
|
||||
1. **निकालने के समय की उत्पत्ति** (देखें `extraction-time-provenance.md`): दस्तावेज़ → पृष्ठ → भाग → किनारा संबंधों को इनपुट के दौरान रिकॉर्ड करता है। `urn:graph:source` नामक ग्राफ में संग्रहीत, `prov:wasDerivedFrom` का उपयोग करके।
|
||||
|
||||
2. **क्वेरी-टाइम व्याख्यात्मकता** (देखें `query-time-explainability.md`): GraphRAG प्रश्नों के दौरान प्रश्न → अन्वेषण → फोकस → संश्लेषण श्रृंखला को रिकॉर्ड करता है। `urn:graph:retrieval` नामक ग्राफ में संग्रहीत।
|
||||
|
||||
वर्तमान सीमाएँ:
|
||||
प्रसंस्करण के बाद दस्तावेज़ पदानुक्रम को देखने का कोई आसान तरीका नहीं है
|
||||
व्याख्यात्मकता डेटा देखने के लिए ट्रिपल को मैन्युअल रूप से क्वेरी करना होगा
|
||||
GraphRAG सत्र का कोई समेकित दृश्य नहीं है
|
||||
|
||||
## तकनीकी डिज़ाइन
|
||||
|
||||
### टूल 1: tg-show-document-hierarchy
|
||||
|
||||
**उद्देश्य**: एक दस्तावेज़ आईडी को देखते हुए, सभी व्युत्पन्न संस्थाओं को पार करें और प्रदर्शित करें।
|
||||
|
||||
**उपयोग**:
|
||||
```bash
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:abc123"
|
||||
tg-show-document-hierarchy --show-content --max-content 500 "urn:trustgraph:doc:abc123"
|
||||
```
|
||||
|
||||
**तर्क**:
|
||||
| तर्क | विवरण |
|
||||
|-----|-------------|
|
||||
| `document_id` | दस्तावेज़ यूआरआई (स्थानिक) |
|
||||
| `-u/--api-url` | गेटवे यूआरएल (डिफ़ॉल्ट: `$TRUSTGRAPH_URL`) |
|
||||
| `-t/--token` | ऑथ टोकन (डिफ़ॉल्ट: `$TRUSTGRAPH_TOKEN`) |
|
||||
| `-U/--user` | उपयोगकर्ता आईडी (डिफ़ॉल्ट: `trustgraph`) |
|
||||
| `-C/--collection` | संग्रह (डिफ़ॉल्ट: `default`) |
|
||||
| `--show-content` | ब्लॉब/दस्तावेज़ सामग्री शामिल करें |
|
||||
| `--max-content` | प्रति ब्लॉब अधिकतम अक्षर (डिफ़ॉल्ट: 200) |
|
||||
| `--format` | आउटपुट: `tree` (डिफ़ॉल्ट), `json` |
|
||||
|
||||
**कार्यान्वयन**:
|
||||
1. ट्रिपल क्वेरी करें: `?child prov:wasDerivedFrom <document_id>` in `urn:graph:source`
|
||||
2. प्रत्येक परिणाम के बच्चों को पुनरावर्ती रूप से क्वेरी करें
|
||||
3. ट्री संरचना बनाएं: दस्तावेज़ → पृष्ठ → भाग
|
||||
4. यदि `--show-content`, तो लाइब्रेरियन एपीआई से सामग्री प्राप्त करें
|
||||
5. इंडेंटेड ट्री या JSON के रूप में प्रदर्शित करें
|
||||
|
||||
**आउटपुट उदाहरण**:
|
||||
```
|
||||
Document: urn:trustgraph:doc:abc123
|
||||
Title: "Sample PDF"
|
||||
Type: application/pdf
|
||||
|
||||
└── Page 1: urn:trustgraph:doc:abc123/p1
|
||||
├── Chunk 0: urn:trustgraph:doc:abc123/p1/c0
|
||||
│ Content: "The quick brown fox..." [truncated]
|
||||
└── Chunk 1: urn:trustgraph:doc:abc123/p1/c1
|
||||
Content: "Machine learning is..." [truncated]
|
||||
```
|
||||
|
||||
### टूल 2: tg-list-explain-traces
|
||||
|
||||
**उद्देश्य**: एक संग्रह में सभी ग्राफ़आरएजी सत्रों (प्रश्नों) को सूचीबद्ध करना।
|
||||
|
||||
**उपयोग**:
|
||||
```bash
|
||||
tg-list-explain-traces
|
||||
tg-list-explain-traces --limit 20 --format json
|
||||
```
|
||||
|
||||
**तर्क:**
|
||||
| तर्क | विवरण |
|
||||
|-----|-------------|
|
||||
| `-u/--api-url` | गेटवे यूआरएल |
|
||||
| `-t/--token` | प्रमाणीकरण टोकन |
|
||||
| `-U/--user` | उपयोगकर्ता आईडी |
|
||||
| `-C/--collection` | संग्रह |
|
||||
| `--limit` | अधिकतम परिणाम (डिफ़ॉल्ट: 50) |
|
||||
| `--format` | आउटपुट: `table` (डिफ़ॉल्ट), `json` |
|
||||
|
||||
**कार्यान्वयन:**
|
||||
1. क्वेरी: `?session tg:query ?text` को `urn:graph:retrieval` में |
|
||||
2. क्वेरी टाइमस्टैम्प: `?session prov:startedAtTime ?time` |
|
||||
3. तालिका के रूप में प्रदर्शित करें |
|
||||
|
||||
**आउटपुट उदाहरण:**
|
||||
```
|
||||
Session ID | Question | Time
|
||||
----------------------------------------------|--------------------------------|---------------------
|
||||
urn:trustgraph:question:abc123 | What was the War on Terror? | 2024-01-15 10:30:00
|
||||
urn:trustgraph:question:def456 | Who founded OpenAI? | 2024-01-15 09:15:00
|
||||
```
|
||||
|
||||
### टूल 3: tg-show-explain-trace
|
||||
|
||||
**उद्देश्य**: ग्राफ़आरएजी सत्र के लिए पूर्ण व्याख्या श्रृंखला प्रदर्शित करें।
|
||||
|
||||
**उपयोग**:
|
||||
```bash
|
||||
tg-show-explain-trace "urn:trustgraph:question:abc123"
|
||||
tg-show-explain-trace --max-answer 1000 --show-provenance "urn:trustgraph:question:abc123"
|
||||
```
|
||||
|
||||
**तर्क:**
|
||||
| तर्क | विवरण |
|
||||
|-----|-------------|
|
||||
| `question_id` | प्रश्न URI (स्थानिक) |
|
||||
| `-u/--api-url` | गेटवे URL |
|
||||
| `-t/--token` | प्रमाणीकरण टोकन |
|
||||
| `-U/--user` | उपयोगकर्ता ID |
|
||||
| `-C/--collection` | संग्रह |
|
||||
| `--max-answer` | उत्तर के लिए अधिकतम अक्षर (डिफ़ॉल्ट: 500) |
|
||||
| `--show-provenance` | स्रोत दस्तावेजों तक किनारों को ट्रेस करें |
|
||||
| `--format` | आउटपुट: `text` (डिफ़ॉल्ट), `json` |
|
||||
|
||||
**कार्यान्वयन:**
|
||||
1. `tg:query` विधेय से प्रश्न पाठ प्राप्त करें।
|
||||
2. अन्वेषण खोजें: `?exp prov:wasGeneratedBy <question_id>`
|
||||
3. फोकस खोजें: `?focus prov:wasDerivedFrom <exploration_id>`
|
||||
4. चयनित किनारों को प्राप्त करें: `<focus_id> tg:selectedEdge ?edge`
|
||||
5. प्रत्येक किनारे के लिए, `tg:edge` (उद्धृत ट्रिपल) और `tg:reasoning` प्राप्त करें।
|
||||
6. संश्लेषण खोजें: `?synth prov:wasDerivedFrom <focus_id>`
|
||||
7. लाइब्रेरियन के माध्यम से `tg:document` से उत्तर प्राप्त करें।
|
||||
8. यदि `--show-provenance`, तो स्रोत दस्तावेजों तक किनारों को ट्रेस करें।
|
||||
|
||||
**आउटपुट उदाहरण:**
|
||||
```
|
||||
=== GraphRAG Session: urn:trustgraph:question:abc123 ===
|
||||
|
||||
Question: What was the War on Terror?
|
||||
Time: 2024-01-15 10:30:00
|
||||
|
||||
--- Exploration ---
|
||||
Retrieved 50 edges from knowledge graph
|
||||
|
||||
--- Focus (Edge Selection) ---
|
||||
Selected 12 edges:
|
||||
|
||||
1. (War on Terror, definition, "A military campaign...")
|
||||
Reasoning: Directly defines the subject of the query
|
||||
Source: chunk → page 2 → "Beyond the Vigilant State"
|
||||
|
||||
2. (Guantanamo Bay, part_of, War on Terror)
|
||||
Reasoning: Shows key component of the campaign
|
||||
|
||||
--- Synthesis ---
|
||||
Answer:
|
||||
The War on Terror was a military campaign initiated...
|
||||
[truncated at 500 chars]
|
||||
```
|
||||
|
||||
## बनाने के लिए फ़ाइलें
|
||||
|
||||
| फ़ाइल | उद्देश्य |
|
||||
|------|---------|
|
||||
| `trustgraph-cli/trustgraph/cli/show_document_hierarchy.py` | टूल 1 |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | टूल 2 |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | टूल 3 |
|
||||
|
||||
## बदलने के लिए फ़ाइलें
|
||||
|
||||
| फ़ाइल | परिवर्तन |
|
||||
|------|--------|
|
||||
| `trustgraph-cli/setup.py` | console_scripts प्रविष्टियाँ जोड़ें |
|
||||
|
||||
## कार्यान्वयन नोट्स
|
||||
|
||||
1. **बाइनरी सामग्री सुरक्षा**: UTF-8 डिकोड करने का प्रयास करें; यदि विफल रहता है, तो `[Binary: {size} bytes]` प्रदर्शित करें।
|
||||
2. **छंटनी**: `--max-content`/`--max-answer` का सम्मान करें जिसमें `[truncated]` संकेतक हो।
|
||||
3. **उद्धृत तिगुट**: `tg:edge` विधेय से RDF-स्टार प्रारूप को पार्स करें।
|
||||
4. **पैटर्न**: `query_graph.py` से मौजूदा CLI पैटर्न का पालन करें।
|
||||
|
||||
## सुरक्षा विचार
|
||||
|
||||
सभी क्वेरी उपयोगकर्ता/संग्रह सीमाओं का सम्मान करती हैं।
|
||||
`--token` या `$TRUSTGRAPH_TOKEN` के माध्यम से टोकन प्रमाणीकरण समर्थित है।
|
||||
|
||||
## परीक्षण रणनीति
|
||||
|
||||
नमूना डेटा के साथ मैन्युअल सत्यापन:
|
||||
```bash
|
||||
# Load a test document
|
||||
tg-load-pdf -f test.pdf -c test-collection
|
||||
|
||||
# Verify hierarchy
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:test"
|
||||
|
||||
# Run a GraphRAG query with explainability
|
||||
tg-invoke-graph-rag --explainable -q "Test question"
|
||||
|
||||
# List and inspect traces
|
||||
tg-list-explain-traces
|
||||
tg-show-explain-trace "urn:trustgraph:question:xxx"
|
||||
```
|
||||
|
||||
## संदर्भ
|
||||
|
||||
क्वेरी-टाइम व्याख्यात्मकता: `docs/tech-specs/query-time-explainability.md`
|
||||
निष्कर्षण-टाइम उत्पत्ति: `docs/tech-specs/extraction-time-provenance.md`
|
||||
मौजूदा CLI उदाहरण: `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py`
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Explainability CLI Technical Specification"
|
||||
parent: "Tech Specs"
|
||||
---
|
||||
|
||||
# Explainability CLI Technical Specification
|
||||
|
||||
## Status
|
||||
|
|
|
|||
228
docs/tech-specs/explainability-cli.pt.md
Normal file
228
docs/tech-specs/explainability-cli.pt.md
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Especificação Técnica da Interface de Linha de Comando (CLI) para Explicabilidade"
|
||||
parent: "Portuguese (Beta)"
|
||||
---
|
||||
|
||||
# Especificação Técnica da Interface de Linha de Comando (CLI) para Explicabilidade
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Status
|
||||
|
||||
Rascunho
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Esta especificação descreve ferramentas de linha de comando para depurar e explorar dados de explicabilidade no TrustGraph. Essas ferramentas permitem que os usuários rastreiem como as respostas foram derivadas e depurem a cadeia de origem desde as arestas até os documentos de origem.
|
||||
|
||||
Três ferramentas de linha de comando:
|
||||
|
||||
1. **`tg-show-document-hierarchy`** - Mostrar a hierarquia de documento → página → trecho → aresta
|
||||
2. **`tg-list-explain-traces`** - Listar todas as sessões GraphRAG com perguntas
|
||||
3. **`tg-show-explain-trace`** - Mostrar o rastreamento completo de explicabilidade para uma sessão
|
||||
|
||||
## Objetivos
|
||||
|
||||
**Depuração**: Permitir que os desenvolvedores inspecionem os resultados do processamento de documentos
|
||||
**Auditabilidade**: Rastrear qualquer fato extraído de volta ao seu documento de origem
|
||||
**Transparência**: Mostrar exatamente como o GraphRAG derivou uma resposta
|
||||
**Usabilidade**: Interface de linha de comando simples com configurações padrão sensatas
|
||||
|
||||
## Contexto
|
||||
|
||||
O TrustGraph possui dois sistemas de rastreabilidade:
|
||||
|
||||
1. **Rastreabilidade em tempo de extração** (veja `extraction-time-provenance.md`): Registra os relacionamentos de documento → página → trecho → aresta durante a ingestão. Armazenado em um grafo chamado `urn:graph:source` usando `prov:wasDerivedFrom`.
|
||||
|
||||
2. **Explicabilidade em tempo de consulta** (veja `query-time-explainability.md`): Registra a cadeia de pergunta → exploração → foco → síntese durante as consultas GraphRAG. Armazenado em um grafo chamado `urn:graph:retrieval`.
|
||||
|
||||
Limitações atuais:
|
||||
Não há uma maneira fácil de visualizar a hierarquia de documentos após o processamento
|
||||
É necessário consultar manualmente as triplas para ver os dados de explicabilidade
|
||||
Não há uma visão consolidada de uma sessão GraphRAG
|
||||
|
||||
## Design Técnico
|
||||
|
||||
### Ferramenta 1: tg-show-document-hierarchy
|
||||
|
||||
**Propósito**: Dado um ID de documento, percorrer e exibir todas as entidades derivadas.
|
||||
|
||||
**Uso**:
|
||||
```bash
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:abc123"
|
||||
tg-show-document-hierarchy --show-content --max-content 500 "urn:trustgraph:doc:abc123"
|
||||
```
|
||||
|
||||
**Argumentos**:
|
||||
| Arg | Descrição |
|
||||
|-----|-------------|
|
||||
| `document_id` | URI do documento (posicional) |
|
||||
| `-u/--api-url` | URL do gateway (padrão: `$TRUSTGRAPH_URL`) |
|
||||
| `-t/--token` | Token de autenticação (padrão: `$TRUSTGRAPH_TOKEN`) |
|
||||
| `-U/--user` | ID do usuário (padrão: `trustgraph`) |
|
||||
| `-C/--collection` | Coleção (padrão: `default`) |
|
||||
| `--show-content` | Incluir conteúdo do blob/documento |
|
||||
| `--max-content` | Máximo de caracteres por blob (padrão: 200) |
|
||||
| `--format` | Saída: `tree` (padrão), `json` |
|
||||
|
||||
**Implementação**:
|
||||
1. Consultar triplas: `?child prov:wasDerivedFrom <document_id>` em `urn:graph:source`
|
||||
2. Consultar recursivamente os filhos de cada resultado
|
||||
3. Construir estrutura de árvore: Documento → Páginas → Blocos
|
||||
4. Se `--show-content`, buscar conteúdo da API do bibliotecário
|
||||
5. Exibir como árvore indentada ou JSON
|
||||
|
||||
**Exemplo de Saída**:
|
||||
```
|
||||
Document: urn:trustgraph:doc:abc123
|
||||
Title: "Sample PDF"
|
||||
Type: application/pdf
|
||||
|
||||
└── Page 1: urn:trustgraph:doc:abc123/p1
|
||||
├── Chunk 0: urn:trustgraph:doc:abc123/p1/c0
|
||||
│ Content: "The quick brown fox..." [truncated]
|
||||
└── Chunk 1: urn:trustgraph:doc:abc123/p1/c1
|
||||
Content: "Machine learning is..." [truncated]
|
||||
```
|
||||
|
||||
### Ferramenta 2: tg-list-explain-traces
|
||||
|
||||
**Propósito**: Listar todas as sessões (perguntas) do GraphRAG em uma coleção.
|
||||
|
||||
**Uso**:
|
||||
```bash
|
||||
tg-list-explain-traces
|
||||
tg-list-explain-traces --limit 20 --format json
|
||||
```
|
||||
|
||||
**Argumentos**:
|
||||
| Arg | Descrição |
|
||||
|-----|-------------|
|
||||
| `-u/--api-url` | URL do gateway |
|
||||
| `-t/--token` | Token de autenticação |
|
||||
| `-U/--user` | ID do usuário |
|
||||
| `-C/--collection` | Coleção |
|
||||
| `--limit` | Resultados máximos (padrão: 50) |
|
||||
| `--format` | Saída: `table` (padrão), `json` |
|
||||
|
||||
**Implementação**:
|
||||
1. Consulta: `?session tg:query ?text` em `urn:graph:retrieval`
|
||||
2. Consulta de carimbos de data/hora: `?session prov:startedAtTime ?time`
|
||||
3. Exibir como tabela
|
||||
|
||||
**Exemplo de Saída**:
|
||||
```
|
||||
Session ID | Question | Time
|
||||
----------------------------------------------|--------------------------------|---------------------
|
||||
urn:trustgraph:question:abc123 | What was the War on Terror? | 2024-01-15 10:30:00
|
||||
urn:trustgraph:question:def456 | Who founded OpenAI? | 2024-01-15 09:15:00
|
||||
```
|
||||
|
||||
### Ferramenta 3: tg-show-explain-trace
|
||||
|
||||
**Propósito**: Mostrar a cascata completa de explicabilidade para uma sessão GraphRAG.
|
||||
|
||||
**Uso**:
|
||||
```bash
|
||||
tg-show-explain-trace "urn:trustgraph:question:abc123"
|
||||
tg-show-explain-trace --max-answer 1000 --show-provenance "urn:trustgraph:question:abc123"
|
||||
```
|
||||
|
||||
**Argumentos**:
|
||||
| Arg | Descrição |
|
||||
|-----|-------------|
|
||||
| `question_id` | URI da pergunta (posicional) |
|
||||
| `-u/--api-url` | URL do gateway |
|
||||
| `-t/--token` | Token de autenticação |
|
||||
| `-U/--user` | ID do usuário |
|
||||
| `-C/--collection` | Coleção |
|
||||
| `--max-answer` | Número máximo de caracteres para a resposta (padrão: 500) |
|
||||
| `--show-provenance` | Rastrear arestas para documentos de origem |
|
||||
| `--format` | Saída: `text` (padrão), `json` |
|
||||
|
||||
**Implementação**:
|
||||
1. Obter o texto da pergunta do predicado `tg:query`
|
||||
2. Encontrar a exploração: `?exp prov:wasGeneratedBy <question_id>`
|
||||
3. Encontrar o foco: `?focus prov:wasDerivedFrom <exploration_id>`
|
||||
4. Obter as arestas selecionadas: `<focus_id> tg:selectedEdge ?edge`
|
||||
5. Para cada aresta, obter `tg:edge` (tripla entre aspas) e `tg:reasoning`
|
||||
6. Encontrar a síntese: `?synth prov:wasDerivedFrom <focus_id>`
|
||||
7. Obter a resposta de `tg:document` através do bibliotecário
|
||||
8. Se `--show-provenance`, rastrear as arestas para os documentos de origem
|
||||
|
||||
**Exemplo de Saída**:
|
||||
```
|
||||
=== GraphRAG Session: urn:trustgraph:question:abc123 ===
|
||||
|
||||
Question: What was the War on Terror?
|
||||
Time: 2024-01-15 10:30:00
|
||||
|
||||
--- Exploration ---
|
||||
Retrieved 50 edges from knowledge graph
|
||||
|
||||
--- Focus (Edge Selection) ---
|
||||
Selected 12 edges:
|
||||
|
||||
1. (War on Terror, definition, "A military campaign...")
|
||||
Reasoning: Directly defines the subject of the query
|
||||
Source: chunk → page 2 → "Beyond the Vigilant State"
|
||||
|
||||
2. (Guantanamo Bay, part_of, War on Terror)
|
||||
Reasoning: Shows key component of the campaign
|
||||
|
||||
--- Synthesis ---
|
||||
Answer:
|
||||
The War on Terror was a military campaign initiated...
|
||||
[truncated at 500 chars]
|
||||
```
|
||||
|
||||
## Arquivos a Criar
|
||||
|
||||
| Arquivo | Propósito |
|
||||
|------|---------|
|
||||
| `trustgraph-cli/trustgraph/cli/show_document_hierarchy.py` | Ferramenta 1 |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | Ferramenta 2 |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | Ferramenta 3 |
|
||||
|
||||
## Arquivos a Modificar
|
||||
|
||||
| Arquivo | Alteração |
|
||||
|------|--------|
|
||||
| `trustgraph-cli/setup.py` | Adicionar entradas de console_scripts |
|
||||
|
||||
## Notas de Implementação
|
||||
|
||||
1. **Segurança do conteúdo binário**: Tente decodificar UTF-8; se falhar, mostre `[Binary: {size} bytes]`
|
||||
2. **Truncamento**: Respeite `--max-content`/`--max-answer` com indicador `[truncated]`
|
||||
3. **Triplas entre aspas**: Analise o formato RDF-star a partir do predicado `tg:edge`
|
||||
4. **Padrões**: Siga os padrões de CLI existentes a partir de `query_graph.py`
|
||||
|
||||
## Considerações de Segurança
|
||||
|
||||
Todas as consultas respeitam os limites de usuário/coleção
|
||||
Autenticação por token suportada via `--token` ou `$TRUSTGRAPH_TOKEN`
|
||||
|
||||
## Estratégia de Teste
|
||||
|
||||
Verificação manual com dados de amostra:
|
||||
```bash
|
||||
# Load a test document
|
||||
tg-load-pdf -f test.pdf -c test-collection
|
||||
|
||||
# Verify hierarchy
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:test"
|
||||
|
||||
# Run a GraphRAG query with explainability
|
||||
tg-invoke-graph-rag --explainable -q "Test question"
|
||||
|
||||
# List and inspect traces
|
||||
tg-list-explain-traces
|
||||
tg-show-explain-trace "urn:trustgraph:question:xxx"
|
||||
```
|
||||
|
||||
## Referências
|
||||
|
||||
Explicabilidade em tempo de consulta: `docs/tech-specs/query-time-explainability.md`
|
||||
Proveniência em tempo de extração: `docs/tech-specs/extraction-time-provenance.md`
|
||||
Exemplo de CLI existente: `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py`
|
||||
228
docs/tech-specs/explainability-cli.ru.md
Normal file
228
docs/tech-specs/explainability-cli.ru.md
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Техническая спецификация CLI для Explainability"
|
||||
parent: "Russian (Beta)"
|
||||
---
|
||||
|
||||
# Техническая спецификация CLI для Explainability
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Статус
|
||||
|
||||
Черновик
|
||||
|
||||
## Обзор
|
||||
|
||||
Эта спецификация описывает инструменты командной строки для отладки и изучения данных explainability в TrustGraph. Эти инструменты позволяют пользователям отслеживать, как были получены ответы, и отлаживать цепочку происхождения от ребер до исходных документов.
|
||||
|
||||
Три инструмента командной строки:
|
||||
|
||||
1. **`tg-show-document-hierarchy`** - Отображение иерархии документ → страница → фрагмент → ребро
|
||||
2. **`tg-list-explain-traces`** - Список всех сессий GraphRAG с вопросами
|
||||
3. **`tg-show-explain-trace`** - Отображение полной цепочки explainability для сессии
|
||||
|
||||
## Цели
|
||||
|
||||
**Отладка**: Предоставить разработчикам возможность просматривать результаты обработки документов.
|
||||
**Прослеживаемость**: Отслеживать любой извлеченный факт до его исходного документа.
|
||||
**Прозрачность**: Показать, как GraphRAG получил ответ.
|
||||
**Удобство использования**: Простой интерфейс командной строки с разумными значениями по умолчанию.
|
||||
|
||||
## Предыстория
|
||||
|
||||
TrustGraph имеет две системы отслеживания происхождения:
|
||||
|
||||
1. **Отслеживание происхождения во время извлечения** (см. `extraction-time-provenance.md`): Записывает отношения документ → страница → фрагмент → ребро во время импорта. Хранится в графе с именем `urn:graph:source`, используя `prov:wasDerivedFrom`.
|
||||
|
||||
2. **Explainability во время запроса** (см. `query-time-explainability.md`): Записывает цепочку вопрос → исследование → фокус → синтез во время запросов GraphRAG. Хранится в графе с именем `urn:graph:retrieval`.
|
||||
|
||||
Текущие ограничения:
|
||||
Нет простого способа визуализации иерархии документов после обработки.
|
||||
Необходимо вручную запрашивать тройки для просмотра данных explainability.
|
||||
Нет единого представления сессии GraphRAG.
|
||||
|
||||
## Технический дизайн
|
||||
|
||||
### Инструмент 1: tg-show-document-hierarchy
|
||||
|
||||
**Назначение**: При заданном идентификаторе документа, обходит и отображает все производные сущности.
|
||||
|
||||
**Использование**:
|
||||
```bash
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:abc123"
|
||||
tg-show-document-hierarchy --show-content --max-content 500 "urn:trustgraph:doc:abc123"
|
||||
```
|
||||
|
||||
**Аргументы**:
|
||||
| Аргумент | Описание |
|
||||
|-----|-------------|
|
||||
| `document_id` | URI документа (позиционный) |
|
||||
| `-u/--api-url` | URL шлюза (по умолчанию: `$TRUSTGRAPH_URL`) |
|
||||
| `-t/--token` | Токен авторизации (по умолчанию: `$TRUSTGRAPH_TOKEN`) |
|
||||
| `-U/--user` | Идентификатор пользователя (по умолчанию: `trustgraph`) |
|
||||
| `-C/--collection` | Коллекция (по умолчанию: `default`) |
|
||||
| `--show-content` | Включить содержимое блоба/документа |
|
||||
| `--max-content` | Максимальное количество символов на блоб (по умолчанию: 200) |
|
||||
| `--format` | Вывод: `tree` (по умолчанию), `json` |
|
||||
|
||||
**Реализация**:
|
||||
1. Запрос троек: `?child prov:wasDerivedFrom <document_id>` в `urn:graph:source`
|
||||
2. Рекурсивный запрос дочерних элементов каждого результата
|
||||
3. Построение древовидной структуры: Документ → Страницы → Части
|
||||
4. Если `--show-content`, получение содержимого из API librarian
|
||||
5. Отображение в виде отформатированного дерева или JSON
|
||||
|
||||
**Пример вывода**:
|
||||
```
|
||||
Document: urn:trustgraph:doc:abc123
|
||||
Title: "Sample PDF"
|
||||
Type: application/pdf
|
||||
|
||||
└── Page 1: urn:trustgraph:doc:abc123/p1
|
||||
├── Chunk 0: urn:trustgraph:doc:abc123/p1/c0
|
||||
│ Content: "The quick brown fox..." [truncated]
|
||||
└── Chunk 1: urn:trustgraph:doc:abc123/p1/c1
|
||||
Content: "Machine learning is..." [truncated]
|
||||
```
|
||||
|
||||
### Инструмент 2: tg-list-explain-traces
|
||||
|
||||
**Назначение**: Вывести список всех сессий GraphRAG (вопросов) в коллекции.
|
||||
|
||||
**Использование**:
|
||||
```bash
|
||||
tg-list-explain-traces
|
||||
tg-list-explain-traces --limit 20 --format json
|
||||
```
|
||||
|
||||
**Аргументы**:
|
||||
| Аргумент | Описание |
|
||||
|-----|-------------|
|
||||
| `-u/--api-url` | URL шлюза |
|
||||
| `-t/--token` | Токен авторизации |
|
||||
| `-U/--user` | Идентификатор пользователя |
|
||||
| `-C/--collection` | Коллекция |
|
||||
| `--limit` | Максимальное количество результатов (по умолчанию: 50) |
|
||||
| `--format` | Вывод: `table` (по умолчанию), `json` |
|
||||
|
||||
**Реализация**:
|
||||
1. Запрос: `?session tg:query ?text` в `urn:graph:retrieval`
|
||||
2. Запрос временных меток: `?session prov:startedAtTime ?time`
|
||||
3. Отображение в виде таблицы
|
||||
|
||||
**Пример вывода**:
|
||||
```
|
||||
Session ID | Question | Time
|
||||
----------------------------------------------|--------------------------------|---------------------
|
||||
urn:trustgraph:question:abc123 | What was the War on Terror? | 2024-01-15 10:30:00
|
||||
urn:trustgraph:question:def456 | Who founded OpenAI? | 2024-01-15 09:15:00
|
||||
```
|
||||
|
||||
### Инструмент 3: tg-show-explain-trace
|
||||
|
||||
**Назначение**: Отображение полной цепочки объяснений для сеанса GraphRAG.
|
||||
|
||||
**Использование**:
|
||||
```bash
|
||||
tg-show-explain-trace "urn:trustgraph:question:abc123"
|
||||
tg-show-explain-trace --max-answer 1000 --show-provenance "urn:trustgraph:question:abc123"
|
||||
```
|
||||
|
||||
**Аргументы**:
|
||||
| Аргумент | Описание |
|
||||
|-----|-------------|
|
||||
| `question_id` | URI вопроса (позиционный) |
|
||||
| `-u/--api-url` | URL шлюза |
|
||||
| `-t/--token` | Токен авторизации |
|
||||
| `-U/--user` | Идентификатор пользователя |
|
||||
| `-C/--collection` | Коллекция |
|
||||
| `--max-answer` | Максимальное количество символов для ответа (по умолчанию: 500) |
|
||||
| `--show-provenance` | Проследить связи к исходным документам |
|
||||
| `--format` | Вывод: `text` (по умолчанию), `json` |
|
||||
|
||||
**Реализация**:
|
||||
1. Получить текст вопроса из предиката `tg:query`
|
||||
2. Найти исследование: `?exp prov:wasGeneratedBy <question_id>`
|
||||
3. Найти фокус: `?focus prov:wasDerivedFrom <exploration_id>`
|
||||
4. Получить выбранные связи: `<focus_id> tg:selectedEdge ?edge`
|
||||
5. Для каждой связи, получить `tg:edge` (цитируемая тройка) и `tg:reasoning`
|
||||
6. Найти синтез: `?synth prov:wasDerivedFrom <focus_id>`
|
||||
7. Получить ответ из `tg:document` через библиотекаря
|
||||
8. Если `--show-provenance`, проследить связи к исходным документам
|
||||
|
||||
**Пример вывода**:
|
||||
```
|
||||
=== GraphRAG Session: urn:trustgraph:question:abc123 ===
|
||||
|
||||
Question: What was the War on Terror?
|
||||
Time: 2024-01-15 10:30:00
|
||||
|
||||
--- Exploration ---
|
||||
Retrieved 50 edges from knowledge graph
|
||||
|
||||
--- Focus (Edge Selection) ---
|
||||
Selected 12 edges:
|
||||
|
||||
1. (War on Terror, definition, "A military campaign...")
|
||||
Reasoning: Directly defines the subject of the query
|
||||
Source: chunk → page 2 → "Beyond the Vigilant State"
|
||||
|
||||
2. (Guantanamo Bay, part_of, War on Terror)
|
||||
Reasoning: Shows key component of the campaign
|
||||
|
||||
--- Synthesis ---
|
||||
Answer:
|
||||
The War on Terror was a military campaign initiated...
|
||||
[truncated at 500 chars]
|
||||
```
|
||||
|
||||
## Файлы для создания
|
||||
|
||||
| Файл | Назначение |
|
||||
|------|---------|
|
||||
| `trustgraph-cli/trustgraph/cli/show_document_hierarchy.py` | Инструмент 1 |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | Инструмент 2 |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | Инструмент 3 |
|
||||
|
||||
## Файлы для изменения
|
||||
|
||||
| Файл | Изменение |
|
||||
|------|--------|
|
||||
| `trustgraph-cli/setup.py` | Добавить записи в console_scripts |
|
||||
|
||||
## Замечания по реализации
|
||||
|
||||
1. **Безопасность двоичного содержимого**: Попробуйте декодировать в UTF-8; если не удается, отобразите `[Binary: {size} bytes]`.
|
||||
2. **Усечение**: Соблюдайте `--max-content`/`--max-answer` с индикатором `[truncated]`.
|
||||
3. **Тройки в кавычках**: Разберите формат RDF-star из предиката `tg:edge`.
|
||||
4. **Шаблоны**: Следуйте существующим шаблонам CLI из `query_graph.py`.
|
||||
|
||||
## Вопросы безопасности
|
||||
|
||||
Все запросы соответствуют границам пользователя/коллекции.
|
||||
Поддерживается аутентификация по токену через `--token` или `$TRUSTGRAPH_TOKEN`.
|
||||
|
||||
## Стратегия тестирования
|
||||
|
||||
Ручная проверка с использованием образцовых данных:
|
||||
```bash
|
||||
# Load a test document
|
||||
tg-load-pdf -f test.pdf -c test-collection
|
||||
|
||||
# Verify hierarchy
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:test"
|
||||
|
||||
# Run a GraphRAG query with explainability
|
||||
tg-invoke-graph-rag --explainable -q "Test question"
|
||||
|
||||
# List and inspect traces
|
||||
tg-list-explain-traces
|
||||
tg-show-explain-trace "urn:trustgraph:question:xxx"
|
||||
```
|
||||
|
||||
## Ссылки
|
||||
|
||||
Объяснимость во время выполнения запроса: `docs/tech-specs/query-time-explainability.md`
|
||||
Происхождение во время извлечения: `docs/tech-specs/extraction-time-provenance.md`
|
||||
Существующий пример интерфейса командной строки: `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py`
|
||||
228
docs/tech-specs/explainability-cli.sw.md
Normal file
228
docs/tech-specs/explainability-cli.sw.md
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Maelezo ya Kiufundi ya Zana za Amri (CLI) za Ufafanuzi"
|
||||
parent: "Swahili (Beta)"
|
||||
---
|
||||
|
||||
# Maelezo ya Kiufundi ya Zana za Amri (CLI) za Ufafanuzi
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## Hali
|
||||
|
||||
Rasimu
|
||||
|
||||
## Muhtasari
|
||||
|
||||
Maelezo haya yanaeleza zana za amri (CLI) za kuchanganua na kuchunguza data ya ufafanuzi katika TrustGraph. Zana hizi zinawawezesha watumiaji kufuatilia jinsi majibu yalivyopatikana na kuchanganua mnyororo wa asili kutoka kwa uhusiano (edges) hadi kwenye nyaraka za asili.
|
||||
|
||||
Zana tatu za CLI:
|
||||
|
||||
1. **`tg-show-document-hierarchy`** - Onyesha hierarkia ya nyaraka → kurasa → vipande → uhusiano
|
||||
2. **`tg-list-explain-traces`** - Orodha ya vipindi vyote vya GraphRAG na maswali
|
||||
3. **`tg-show-explain-trace`** - Onyesha mnyororo kamili wa ufafanuzi kwa kipindi
|
||||
|
||||
## Lengo
|
||||
|
||||
**Uchanganuzi**: Kuwawezesha watengenezaji kuchunguza matokeo ya usindikaji wa nyaraka
|
||||
**Ufuatiliaji**: Kufuatilia ukweli wowote uliopatikana hadi kwenye nyaraka yake ya asili
|
||||
**Unyonyaji**: Kuonyesha jinsi GraphRAG ilivyopata jibu
|
||||
**Urahisi wa Matumizi**: Kiolesura rahisi cha CLI na mipangilio ya kawaida
|
||||
|
||||
## Asili
|
||||
|
||||
TrustGraph ina mifumo miwili ya asili:
|
||||
|
||||
1. **Asili ya wakati wa uundaji** (angalia `extraction-time-provenance.md`): Inarecord uhusiano wa nyaraka → kurasa → vipande → uhusiano wakati wa kuingizwa. Hifadhiwa katika grafu iliyoitwa `urn:graph:source` kwa kutumia `prov:wasDerivedFrom`.
|
||||
|
||||
2. **Ufafanuzi wa wakati wa kuulizia** (angalia `query-time-explainability.md`): Inarecord mnyororo wa swali → uchunguzi → umakini → muhtasari wakati wa maswali ya GraphRAG. Hifadhiwa katika grafu iliyoitwa `urn:graph:retrieval`.
|
||||
|
||||
Mapungufu ya sasa:
|
||||
Hakuna njia rahisi ya kuonyesha hierarkia ya nyaraka baada ya usindikaji
|
||||
Lazima kuulize data ya ufafanuzi kwa kutumia triples
|
||||
Hakuna mtazamo uliochanganywa wa kipindi cha GraphRAG
|
||||
|
||||
## Muundo wa Kiufundi
|
||||
|
||||
### Zana 1: tg-show-document-hierarchy
|
||||
|
||||
**Lengo**: Ikiwa unapokea kitambulisho cha nyaraka, tembea na uonyeshe vitu vyote vilivyotokana.
|
||||
|
||||
**Matumizi**:
|
||||
```bash
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:abc123"
|
||||
tg-show-document-hierarchy --show-content --max-content 500 "urn:trustgraph:doc:abc123"
|
||||
```
|
||||
|
||||
**Vigezo**:
|
||||
| Arg | Maelezo |
|
||||
|-----|-------------|
|
||||
| `document_id` | URI ya hati (ya nafasi) |
|
||||
| `-u/--api-url` | URL ya lango (ya kawaida: `$TRUSTGRAPH_URL`) |
|
||||
| `-t/--token` | Ishara ya uthibitishaji (ya kawaida: `$TRUSTGRAPH_TOKEN`) |
|
||||
| `-U/--user` | Kitambulisho cha mtumiaji (ya kawaida: `trustgraph`) |
|
||||
| `-C/--collection` | Mkusanyiko (ya kawaida: `default`) |
|
||||
| `--show-content` | Jumuisha yaliyomo katika faili/hati |
|
||||
| `--max-content` | Herufi nyingi kwa kila faili (ya kawaida: 200) |
|
||||
| `--format` | Matokeo: `tree` (ya kawaida), `json` |
|
||||
|
||||
**Utendaji**:
|
||||
1. Tafuta data: `?child prov:wasDerivedFrom <document_id>` katika `urn:graph:source`
|
||||
2. Tafuta kwa urudi-urudi watoto wa kila matokeo
|
||||
3. Jenga muundo wa mti: Hati → Kurasa → Sehemu
|
||||
4. Ikiwa `--show-content`, pata yaliyomo kutoka kwa API ya msimamizi
|
||||
5. Onyesha kama mti ulioainishwa au JSON
|
||||
|
||||
**Mfano wa Matokeo**:
|
||||
```
|
||||
Document: urn:trustgraph:doc:abc123
|
||||
Title: "Sample PDF"
|
||||
Type: application/pdf
|
||||
|
||||
└── Page 1: urn:trustgraph:doc:abc123/p1
|
||||
├── Chunk 0: urn:trustgraph:doc:abc123/p1/c0
|
||||
│ Content: "The quick brown fox..." [truncated]
|
||||
└── Chunk 1: urn:trustgraph:doc:abc123/p1/c1
|
||||
Content: "Machine learning is..." [truncated]
|
||||
```
|
||||
|
||||
### Zana 2: tg-list-explain-traces
|
||||
|
||||
**Madhumuni**: Kuorodhesha vipindi vyote vya GraphRAG (maswali) katika mkusanyiko.
|
||||
|
||||
**Matumizi**:
|
||||
```bash
|
||||
tg-list-explain-traces
|
||||
tg-list-explain-traces --limit 20 --format json
|
||||
```
|
||||
|
||||
**Vigezo**:
|
||||
| Arg | Maelezo |
|
||||
|-----|-------------|
|
||||
| `-u/--api-url` | URL ya lango |
|
||||
| `-t/--token` | Token ya uthibitishaji |
|
||||
| `-U/--user` | Kitambulisho cha mtumiaji |
|
||||
| `-C/--collection` | Mkusanyiko |
|
||||
| `--limit` | Matokeo ya juu (ya kawaida: 50) |
|
||||
| `--format` | Matokeo: `table` (ya kawaida), `json` |
|
||||
|
||||
**Utekelezaji**:
|
||||
1. Uliza: `?session tg:query ?text` katika `urn:graph:retrieval`
|
||||
2. Uliza alama za wakati: `?session prov:startedAtTime ?time`
|
||||
3. Onyesha kama jedwali
|
||||
|
||||
**Mfano wa Matokeo**:
|
||||
```
|
||||
Session ID | Question | Time
|
||||
----------------------------------------------|--------------------------------|---------------------
|
||||
urn:trustgraph:question:abc123 | What was the War on Terror? | 2024-01-15 10:30:00
|
||||
urn:trustgraph:question:def456 | Who founded OpenAI? | 2024-01-15 09:15:00
|
||||
```
|
||||
|
||||
### Zana 3: tg-show-explain-trace
|
||||
|
||||
**Madhumuni**: Kuonyesha mnyororo kamili wa uelewaji kwa kipindi cha GraphRAG.
|
||||
|
||||
**Matumizi**:
|
||||
```bash
|
||||
tg-show-explain-trace "urn:trustgraph:question:abc123"
|
||||
tg-show-explain-trace --max-answer 1000 --show-provenance "urn:trustgraph:question:abc123"
|
||||
```
|
||||
|
||||
**Vigezo**:
|
||||
| Arg | Maelezo |
|
||||
|-----|-------------|
|
||||
| `question_id` | URI ya swali (nafasi) |
|
||||
| `-u/--api-url` | URL ya lango |
|
||||
| `-t/--token` | Ishara ya uthibitishaji |
|
||||
| `-U/--user` | Kitambulisho cha mtumiaji |
|
||||
| `-C/--collection` | Mkusanyiko |
|
||||
| `--max-answer` | Idadi ya juu ya herufi kwa jibu (ya kawaida: 500) |
|
||||
| `--show-provenance` | Fuatilia miunganisho hadi kwenye hati za asili |
|
||||
| `--format` | Pato: `text` (ya kawaida), `json` |
|
||||
|
||||
**Utendaji**:
|
||||
1. Pata maandishi ya swali kutoka kwa `tg:query`.
|
||||
2. Tafuta utafutaji: `?exp prov:wasGeneratedBy <question_id>`
|
||||
3. Tafuta umakini: `?focus prov:wasDerivedFrom <exploration_id>`
|
||||
4. Pata miunganisho iliyochaguliwa: `<focus_id> tg:selectedEdge ?edge`
|
||||
5. Kwa kila muunganisho, pata `tg:edge` (triple iliyotiwa mabano) na `tg:reasoning`.
|
||||
6. Tafuta muhtasari: `?synth prov:wasDerivedFrom <focus_id>`
|
||||
7. Pata jibu kutoka kwa `tg:document` kupitia msimamizi wa maktaba.
|
||||
8. Ikiwa `--show-provenance`, fuatilia miunganisho hadi kwenye hati za asili.
|
||||
|
||||
**Mfano wa Pato**:
|
||||
```
|
||||
=== GraphRAG Session: urn:trustgraph:question:abc123 ===
|
||||
|
||||
Question: What was the War on Terror?
|
||||
Time: 2024-01-15 10:30:00
|
||||
|
||||
--- Exploration ---
|
||||
Retrieved 50 edges from knowledge graph
|
||||
|
||||
--- Focus (Edge Selection) ---
|
||||
Selected 12 edges:
|
||||
|
||||
1. (War on Terror, definition, "A military campaign...")
|
||||
Reasoning: Directly defines the subject of the query
|
||||
Source: chunk → page 2 → "Beyond the Vigilant State"
|
||||
|
||||
2. (Guantanamo Bay, part_of, War on Terror)
|
||||
Reasoning: Shows key component of the campaign
|
||||
|
||||
--- Synthesis ---
|
||||
Answer:
|
||||
The War on Terror was a military campaign initiated...
|
||||
[truncated at 500 chars]
|
||||
```
|
||||
|
||||
## Faili Zinazotakazwa Kuundwa
|
||||
|
||||
| Faili | Madhumuni |
|
||||
|------|---------|
|
||||
| `trustgraph-cli/trustgraph/cli/show_document_hierarchy.py` | Chombo 1 |
|
||||
| `trustgraph-cli/trustgraph/cli/list_explain_traces.py` | Chombo 2 |
|
||||
| `trustgraph-cli/trustgraph/cli/show_explain_trace.py` | Chombo 3 |
|
||||
|
||||
## Faili Zinazotakazwa Kurekebishwa
|
||||
|
||||
| Faili | Marekebisho |
|
||||
|------|--------|
|
||||
| `trustgraph-cli/setup.py` | Ongeza vipengele vya `console_scripts` |
|
||||
|
||||
## Maelezo ya Utendaji
|
||||
|
||||
1. **Usalama wa yaliyomo ya binary**: Jaribu kusimbua kwa UTF-8; ikiwa hufanikiwa, onyesha `[Binary: {size} bytes]`
|
||||
2. **Ufupishaji**: Zifuata sheria za `--max-content`/`--max-answer` pamoja na ishara ya `[truncated]`
|
||||
3. **Manuku matatu yaliyotiwa:** Changanua muundo wa RDF-star kutoka kwa `predicate` ya `tg:edge`
|
||||
4. **Mifumo:** Fuata mifumo iliyopo ya CLI kutoka `query_graph.py`
|
||||
|
||||
## Masuala ya Usalama
|
||||
|
||||
Maswali yote yanazingatia mipaka ya mtumiaji/mkusanyiko
|
||||
Uthibitishaji wa token unaoendeshwa kupitia `--token` au `$TRUSTGRAPH_TOKEN`
|
||||
|
||||
## Mkakati wa Upimaji
|
||||
|
||||
Uthibitisho wa mwongozo kwa data ya mfano:
|
||||
```bash
|
||||
# Load a test document
|
||||
tg-load-pdf -f test.pdf -c test-collection
|
||||
|
||||
# Verify hierarchy
|
||||
tg-show-document-hierarchy "urn:trustgraph:doc:test"
|
||||
|
||||
# Run a GraphRAG query with explainability
|
||||
tg-invoke-graph-rag --explainable -q "Test question"
|
||||
|
||||
# List and inspect traces
|
||||
tg-list-explain-traces
|
||||
tg-show-explain-trace "urn:trustgraph:question:xxx"
|
||||
```
|
||||
|
||||
## Marejeleo
|
||||
|
||||
Uwezekano wa kueleza matokeo wakati wa swali: `docs/tech-specs/query-time-explainability.md`
|
||||
Chanzo cha data wakati wa uundaji: `docs/tech-specs/extraction-time-provenance.md`
|
||||
Kifaa cha amri (CLI) cha mfano uliopo: `trustgraph-cli/trustgraph/cli/invoke_graph_rag.py`
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue